2013-04-24
| 00:01 | pppaul | walking is awesome |
| 00:03 | pppaul | i have a walk that turns everything it touches into a set |
| 00:03 | pppaul | :) |
| 00:03 | pppaul | i use walks for datomic stuff too |
| 01:30 | beaky | hello |
| 01:32 | beaky | how do I learn the clojure language? |
| 01:32 | callen | beaky: hello |
| 01:32 | callen | beaky: buy a book |
| 01:32 | callen | beaky: I recommend Cemerick's |
| 01:32 | beaky | ah |
| 01:32 | callen | beaky: SegFaultAX: something |
| 01:32 | callen | beaky: http://www.clojurebook.com/ |
| 01:42 | tdignan | callen: i bought a book |
| 01:43 | tdignan | but I don't know clojure |
| 01:43 | tdignan | what do I do next? |
| 01:43 | tdignan | seriously, I bought the book. idled in the irc for a month, but not a lick of clojure. |
| 01:43 | tdignan | do I have to actually read the book as well? |
| 01:43 | tdignan | tbh, it intimidates me a lot. |
| 01:44 | tdignan | its so unlike anything else i've done. |
| 01:44 | Raynes | Well, you're never going to want to lick the Clojure. |
| 01:45 | tdignan | That is a quite possible outcome. |
| 01:45 | Oddman | tdignan, that's functional programming for you |
| 01:45 | Oddman | :P |
| 01:47 | beaky | clojure looks like scheme |
| 01:47 | callen | Clojure is relatively easy, as far as functional languages go. |
| 01:47 | callen | It's not the "pull brain out of you through your asshole" experience that Haskell represents. |
| 01:48 | tdignan | oh, yeah. i looked at haskell once years ago. |
| 01:48 | callen | looking doesn't really do anything |
| 01:48 | callen | which might explain why you haven't learned Clojure yet either. |
| 01:49 | tdignan | I haven't learned something just for the sake of learning it for a long time. |
| 01:49 | tdignan | usually i just learn the things I need to know to build things. |
| 01:52 | tdignan | I suppose I'm not the only one to give up here. |
| 01:52 | callen | tdignan: why are you here? |
| 01:53 | tdignan | callen: um, I thought idling here and watching people talk about clojure would help to stoke my interest more |
| 01:53 | tdignan | I've been on autojoin for a month |
| 01:58 | beaky | so the bird book is the one to go for for beginners? |
| 01:58 | Pupnik- | ive been working with that one |
| 01:58 | Pupnik- | i think it is good |
| 02:00 | tdignan | looks like there is also a free webcast by the author on may 1st |
| 02:00 | tdignan | ...2012 |
| 02:00 | tdignan | nevermind |
| 02:01 | beaky | what are the challenges to learning clojure? |
| 02:06 | tdignan | beaky: i can tell you why I haven't learned it yet. it's unlike anything else I know, and I don't actually need to learn it. |
| 02:07 | tdignan | i'm sure your challenges will be unique to your own mind. |
| 02:07 | beaky | ah |
| 02:08 | beaky | I know c++ |
| 02:08 | beaky | so I am probably going to have a tough time :D |
| 02:08 | beaky | since clojure is so different from those braces languages |
| 02:10 | beaky | but I want to use it to build a data processing app |
| 02:11 | Raynes | Every single app ever is a data processing app. |
| 02:11 | beaky | heh |
| 02:11 | beaky | apps are just sequences of bits that flip other sequences of bits |
| 02:13 | beaky | clojure doesn't seem particularly object-oriented |
| 02:13 | tdignan | apps are programs that flip tons of redundant sequences of bits so the programmer can actually get done in a reasonable amount of time |
| 02:13 | tdignan | nope. it's a functional language. |
| 02:14 | beaky | functional? like C? |
| 02:14 | tdignan | C is procedural |
| 02:14 | beaky | ah |
| 02:14 | tdignan | the main difference has to do with keeping state. a purely functional program doesn't have it. |
| 02:15 | beaky | so a language like clojure does away with flipping bits |
| 02:15 | tdignan | the bits do flip. the code itself is data. |
| 02:15 | beaky | ah |
| 02:16 | tdignan | so a clojure program, is actually data, that gets read by a parser, which then executes the code... which itself is actually flat text, data :) |
| 02:16 | Chousuke | a purely functional program does have state. it's just explicit and individual states are generally immutable values |
| 02:17 | Chousuke | Haskell takes value-oriented programming to an extreme. even I/O is pure in haskell :P |
| 02:17 | beaky | ah |
| 02:17 | beaky | so a functional programming language just views state as data/values, and functions are just maps between values? |
| 02:18 | beaky | (like mathematical functions) |
| 02:18 | sparkjoy | That's a good way to think of it |
| 02:18 | Chousuke | that's maybe oversimplifying a bit, but yes |
| 02:19 | Chousuke | when you work in a truly "pure" language you need some creativity to be able to do certain things that are "easy" in an impure language (I/O is the usual example) |
| 02:20 | beaky | is IO pure in clojure like haskell? |
| 02:20 | Chousuke | nah, clojure is not a purely functional language |
| 02:20 | beaky | ah, so clojure is more practical ^^ |
| 02:20 | sparkjoy | very much so |
| 02:21 | Chousuke | it's not more practical for that reason |
| 02:21 | Chousuke | it may be more practical because of JVM interop, but not because it's impure |
| 02:21 | callen | tdignan: code being data has nothing to do with being functional, that's homoiconicity. |
| 02:21 | Raynes | It's certainly more practical for people without the patience necessary to learn Haskell well enough to use it properly. |
| 02:22 | callen | Raynes: I don't think the purity is the confusing part with Haskell. |
| 02:22 | Raynes | callen: Wasn't saying it was. |
| 02:22 | Chousuke | the way haskell does IO is instead of "functions" that just do it, IO actions are represented as values that don't actually do anything until the *runtime* "interprets" them |
| 02:22 | callen | fair enough. |
| 02:23 | Chousuke | so you can store those values in data structures and copy them around, since without the runtime interpretation they don't actually have side-effects |
| 02:24 | beaky | so clojure is practical because it runs on the jvm and has seamless java interop and lisp metaprogramming facilities? |
| 02:24 | Chousuke | Clojure is practical if you can use it to solve a problem you have |
| 02:24 | beaky | ah |
| 02:24 | Chousuke | if you can't, it's not practical, in your case. |
| 02:25 | Chousuke | "practical" is very relative |
| 02:25 | Chousuke | Some people would consider Agda to be practical because they need to write formally verifiable software :P |
| 02:25 | beaky | right |
| 02:26 | beaky | I guess sometimes the functional style is very practical |
| 02:26 | Chousuke | it has many benefits |
| 02:26 | Chousuke | the main one, to me, is having fewer things interacting |
| 02:26 | Chousuke | so fewer things to worry about |
| 02:27 | Chousuke | when working with mutable data, in theory anything could interact with anything else at any point during execution, so you have no guarantees, and have to code in a way that minimizes the likelihood of such interactions occurring when not intended |
| 02:28 | Chousuke | if you work with immutable data, you have a guarantee that nothing will affect it short of hardware failure |
| 02:28 | matko | mutability is adventurous, living on the edge |
| 02:29 | matko | there's actually no such guarantees though, are there? Reflection lets you 'break in' at any time if you wish |
| 02:29 | Chousuke | well, that's true. but such violations would be easy to spot |
| 02:30 | Chousuke | you can't do something like that by mistake |
| 02:30 | beaky | in rich hickey's talk about simplifying programs he did mention that immutable data simplifies things a ton; does clojure give lots of help in having immutable data? (C++ isn't really helping much in that area :( ) |
| 02:31 | Chousuke | All of clojure's basic data structures are immutable |
| 02:31 | sparkjoy | immutability is the default in clojure |
| 02:31 | Chousuke | there's also a system for safely handling shared state, with well-defined concurrency semantics |
| 02:32 | sparkjoy | immutable + persistent (e.g. efficient versioning) data structures are really handy and idiomatic |
| 02:33 | sparkjoy | we've been doing a lot of functional style work in an OO language, with somewhat persistent data structures, but it's not idiomatic and sometimes it can be painful |
| 02:33 | Chousuke | personally I find it difficult to work with mutable data nowadays |
| 02:33 | Chousuke | it's frustrating to have to worry about making mistakes. |
| 02:33 | sparkjoy | you find yourself fighting the language a lot - clojure makes these things much easier |
| 02:35 | sparkjoy | right I can't tell you how many times as a library developer I've been handed a mutable collection and wondered, "should I clone this, or is it gonna be stable" |
| 02:35 | Chousuke | say if in python you have a list full of dictionaries full of lists and want to transform it somehow. it ends up being rather painful. |
| 02:36 | Chousuke | especially if you want to hold on to the non-transformed version |
| 02:38 | Chousuke | for example, what if one of the lists you're transforming is being shared with some other part of the code? you've just broken things. |
| 02:38 | Chousuke | it's not fun |
| 02:39 | murtaza52 | (def primitive-conv {:I 1 :V 5 :X 10 :L 50 :C 100 :D 500 :M 1000}) |
| 02:39 | murtaza52 | (defn substraction-rule |
| 02:39 | murtaza52 | [coll] |
| 02:39 | murtaza52 | (map #(if (primitive-conv %1) |
| 02:39 | murtaza52 | (if (< (primitive-conv %1) (primitive-conv %2)) |
| 02:39 | murtaza52 | (list '- %2 %1) |
| 02:39 | murtaza52 | %1) |
| 02:39 | murtaza52 | %1) |
| 02:39 | murtaza52 | coll |
| 02:39 | murtaza52 | (rest coll))) |
| 02:39 | murtaza52 | (substraction-rule b) => (+ (- :L :X) :L :I) |
| 02:39 | murtaza52 | expected => (+ (- :L :X) :I :I) |
| 02:39 | brainproxy | murtaza52: gist or refheap please |
| 02:39 | brainproxy | don't paste in chan |
| 02:39 | murtaza52 | How do I correct the above fn ? |
| 02:39 | murtaza52 | sorry let me do that |
| 02:45 | murtaza52 | Can anyone help is getting this right - https://www.refheap.com/paste/13927 |
| 02:51 | matko | so why is 'ideomatic' so important? Like, I had a debate the other day about (seq collection) vs (not (empty? collection)), where the other guy argued that (seq collection) was the more ideomatic way to check for non-emptyness, and the documentation seems to concur. Why is 'one way' so important? |
| 02:52 | antares_ | matko: it's not more idiomatic. Also, it's a matter of taste. Use (not (empty? …)) if you prefer that. |
| 02:52 | matko | ok, so maybe I have the wrong definition of ideomatic in my head |
| 02:52 | matko | I've really only ever heard this word in clojure context |
| 02:52 | Chousuke | actually using (seq foo) in a boolean context is a Clojure idiom |
| 02:53 | matko | I prefer (not empty? ..) cause it gives true rather than a value |
| 02:53 | matko | err.. messed that up, but you get the idea |
| 02:53 | Chousuke | and (not (empty? foo)) is the same as (not (not (seq foo)) |
| 02:53 | Chousuke | see the definition of empty? |
| 02:53 | matko | reading it now.. |
| 02:54 | Chousuke | idiomatic just means something that is commonly accepted as being good style |
| 02:55 | Chousuke | and an idiom is an instance of that. eg. it's a clojure idiom to use map/filter instead of explicit loops |
| 02:55 | matko | so why does this matter? I mean, 'good style' of course matters, but is (seq foo) truly better style than (not (empty? foo))? I find that rather arbitrary |
| 02:55 | antares_ | but it doesn't have to be the only style |
| 02:55 | Chousuke | matko: it is arbitrary, but that's what makes it an idiom |
| 02:56 | Chousuke | it's the accepted choice among many. |
| 02:56 | matko | >Heh, but what is the purpose of having an accepted choice? |
| 02:56 | Chousuke | well, lots of Clojure functions deal with sequences |
| 02:57 | rodnaph_ | can anyone tell me how to emit a "debugger;" statement via clojurescript? |
| 02:57 | noidi | when there's a Right Way (tm) to do something, it's easy to see what the code is doing just by its shape |
| 02:57 | Chousuke | so (seq foo) fell out from that |
| 02:57 | Chousuke | and it's shorter. and faster :P |
| 02:57 | rodnaph_ | gah! got it, just as i had given up (http://stackoverflow.com/questions/11181752/clojurescript-breakpoints) |
| 02:58 | noidi | in C there's an idiom for iterating over a collection: for (i = 0; i < size; i++). everyone who sees that knows immediately what's going on |
| 02:58 | noidi | of course you could use a while loop there, but that would not be idiomatic, and it would require more thinking from the reader to see what the loop's about |
| 02:58 | Chousuke | noidi: it's also an idiom in C to treat integers as booleans, for whatever reason |
| 02:59 | matko | Chousuke: ah, that makes sense |
| 02:59 | Chousuke | it makes no sense if you start thinking about it but no-one considers it weird at all in the context of C |
| 02:59 | matko | noidi: but I disagree with the idea that (seq foo) looks clearer than (not (empty? foo)) :p |
| 03:00 | noidi | seq vs. not empty? is not the best example of a clojure idiom, as it's one that many people disagree with |
| 03:00 | matko | at least I know a rationale behind it now |
| 03:00 | Chousuke | matko: it doesn't look clearer, but since you should know what seq does if you want to get anything done in Clojure, you learn that particular idiom quite quickly |
| 03:00 | Chousuke | and *then* it will look clearer |
| 03:00 | Chousuke | because it's shorter |
| 03:00 | noidi | a better example might be mapping over a map: (into {} (for [[k v]] m] [k (f v)])) |
| 03:01 | matko | well I come from a common lisp background, so I'm very familiar with using value and nil as true and false.. it just striked me as odd that clojure would do it when it also has boolean values |
| 03:01 | tieTYT | with gen-class, is it possible to pass the :methods in as a variable? I'm not sure how to do that because it needs a symbol in it (the name of the method without the prefix) |
| 03:01 | noidi | you see "into {}" and "for [[k v]] m]" quite often in clojure code |
| 03:01 | Chousuke | matko: booleans are there only for java interop |
| 03:02 | matko | haha really? I thought they were there from scheme |
| 03:03 | Chousuke | it's a wart, but a necessary one |
| 03:03 | Chousuke | it would be difficult to use Java libraries without access to booleans |
| 03:04 | matko | But clojure propositions return true or false as well |
| 03:04 | antares_ | Chousuke: I doubt that |
| 03:04 | Chousuke | that just helps when calling them from Java |
| 03:04 | amalloy | Chousuke: i disagree that booleans are only for java interop |
| 03:04 | Chousuke | most clojure code doesn't really care. |
| 03:05 | Chousuke | amalloy: well, they are useful outside it too, but not required |
| 03:06 | amalloy | lists and numbers aren't required either: we could just work with church encodings in the lambda calculus. but they're easier and more sensible to work with, and so are booleans. why should (= 1 2) return the empty list instead of false? |
| 03:06 | Chousuke | nil is not the empty list |
| 03:06 | Chousuke | () is the empty list |
| 03:07 | matko | wait what.. nil is not '()? |
| 03:07 | Chousuke | I'm just saying that Clojure has no real need for explicit booleans because you could use nil and anything non-nil instead |
| 03:07 | Chousuke | Right. nil is not () |
| 03:07 | matko | wow confused |
| 03:08 | Chousuke | in Clojure nil means "nothing" |
| 03:08 | matko | it also evaluates as true it seems |
| 03:08 | matko | in an if |
| 03:08 | Chousuke | yeah, because it's a value |
| 03:08 | beaky | does clojure have tail-call optimization? |
| 03:08 | sparkjoy | not automatically, beaky - need to use recur explicitly |
| 03:08 | matko | unfortunately it doesn't have tail-call optimization |
| 03:09 | Chousuke | the JVM doesn't guarantee tail-call elimination |
| 03:09 | Chousuke | people get this stuff confused really easily |
| 03:09 | Chousuke | there's a difference between doing tail-call elimination and *guaranteeing* it |
| 03:10 | Chousuke | the latter is an issue of language semantics. the former is just an optimization. |
| 03:10 | sparkjoy | good point |
| 03:10 | beaky | ah |
| 03:11 | beaky | too bad :( |
| 03:11 | matko | so, nil and false are false, everything else is true, and the seq trick works cause seq returns nil rather than the empty list when called on an empty collection |
| 03:11 | matko | this feels.. hackish |
| 03:11 | xxxyxxyxx | oioiiiiiii9o99 |
| 03:11 | xxxyxxyxx | madar chod |
| 03:13 | beaky | what is clojure's associative model for data? |
| 03:13 | beaky | is it like a map? |
| 03:13 | sparkjoy | maps and records |
| 03:14 | beaky | ah neat |
| 03:14 | sparkjoy | records give you associative via a class, higher perf, easy to move to once you've figured out your model with a map |
| 03:15 | Chousuke | matko: the way seq works is that if you have something in a collection, it will returns a seq representing the contents. if there is nothing, it returns nothing (nil) |
| 03:15 | beaky | records are like structs in C, or classes with no methods and all data fields public in java? |
| 03:15 | beaky | or ADTs like in haskell? |
| 03:16 | Chousuke | records are an optimization of maps |
| 03:16 | sparkjoy | public final fields on a gen'd java class |
| 03:16 | matko | Chousuke: I see that, but don't understand the reason for not returning an empty list instead, exept to return something that evaluates to false.. but in that case I don't get why empty list is not false in the first place.. eh, it doesn't matter much |
| 03:17 | Chousuke | matko: it's not false because there are other empty things |
| 03:17 | Chousuke | an empty list is distinct from an empty vector |
| 03:17 | katratxo | matko: only false and nil are "falsy" |
| 03:17 | Chousuke | and I think treating nil as an empty list is a mistake that CL made. |
| 03:18 | sparkjoy | oh interesting point about () and [] - never thought about it that way |
| 03:18 | matko | it made recursing over lists easy |
| 03:18 | matko | (in common lisp) |
| 03:19 | Chousuke | I suppose seqs in clojure are sort of like CL lists in that regard |
| 03:19 | Chousuke | you can recurse until (seq whatever) returns nil |
| 03:20 | Chousuke | and because you're calling seq in the recursion, the function works the same for all seqable data structures |
| 03:20 | matko | yes, I like how clojure made vector and map as easy to use as lists |
| 03:21 | sparkjoy | one quick point about (seq foo) - if foo is a lazy seq, in my experiments this causes foo to materialize. Just tested it on an infinite seq and it materialized the first 32 items. |
| 03:21 | sparkjoy | that surprised me the first time I saw it |
| 03:21 | Chousuke | sparkjoy: yeah it has to force one element to know if there are any |
| 03:21 | sparkjoy | makes me less confident that (seq foo) is faster than (not (empty? foo)) |
| 03:22 | sparkjoy | if you weren't going to materialize it I suppose |
| 03:22 | Chousuke | sparkjoy: it is faster because empty? is defined in terms of seq :P |
| 03:22 | sparkjoy | LOL nm then |
| 03:22 | sparkjoy | that's funny |
| 03:22 | Chousuke | 32 elements getting realized is just an internal optimization (chunking) |
| 03:22 | sparkjoy | yea that's what I figured |
| 03:23 | Chousuke | in general, having sequences with side-effects is a bad idea |
| 03:23 | sparkjoy | yea, I threw a println in a map to test it out |
| 03:23 | sparkjoy | was just curious |
| 03:23 | mthvedt | sequences with side-effects were a pretty fun paradigm for some computations |
| 03:24 | mthvedt | now, you have to be careful about chunks |
| 03:25 | Chousuke | laziness and side-effects don't mix very well with dynamic typing :P |
| 03:27 | mthvedt | chousuke: i can think of a billion procedural languages with dynamic typing |
| 03:27 | Chousuke | actually, any time side-effects are involved you just need to be careful, regardless of the language or its laziness. |
| 03:28 | Chousuke | mthvedt: sure, but lazy + effectful is already a bit of a problem. In Haskell's case, the type system at least helps a bit. |
| 03:29 | mthvedt | well one reason haskell needs that, though, is because it enforces laziness |
| 03:29 | Chousuke | fortunately laziness in Clojure is restricted to sequences so it's easier to control |
| 03:29 | mthvedt | clojure isn't a lazy language, it's an eager in-order language |
| 03:29 | mthvedt | but a lot of lazy paradigms are used |
| 03:30 | mthvedt | because they are useful and convenient |
| 03:30 | Chousuke | I don't mind Haskell's laziness though. There are many useful things you can do only because it is lazy. |
| 03:31 | beaky | haskell avoids success at all costs :D |
| 03:31 | mthvedt | idk, haskell reminds me of the guy who could be a successful manager but would rather be a senior engineer instead |
| 03:32 | mthvedt | where playing with neat ideas > practicality |
| 03:32 | Chousuke | it does make things harder for people trying to figure out how to make things efficient, but the haskell community is full of smart library writers solving that problem. |
| 03:32 | Chousuke | mthvedt: the thing is, those neat ideas turn out to be practical once you get them fleshed out |
| 03:33 | Chousuke | Functors and applicatives are something everyone uses. Monads too. |
| 03:33 | mthvedt | well, monads are like |
| 03:34 | mthvedt | you can do all these neat things with monads and monadic flow control, but that doesn't explain why you need them to write to stdout |
| 03:34 | Chousuke | mthvedt: You don't need monads to write to stdout |
| 03:34 | mthvedt | chousuke: really? hacker news threads have lied to me |
| 03:34 | Chousuke | mthvedt: the thing is, if you want to write to stdout, you have a monad |
| 03:35 | Chousuke | it's not that monad -> ability to write to stdout |
| 03:35 | Chousuke | it's that ability to write to stdout -> monad |
| 03:36 | mthvedt | i have to confess that's not very eludicating |
| 03:36 | Chousuke | mthvedt: I assume you already understand that haskell is pure? basically everything is an immutable, side-effect free value |
| 03:37 | Chousuke | representing side-effects in a system like this may seem difficult at first but it's really not |
| 03:37 | Chousuke | all you need is the ability to treat the "instructions" as values |
| 03:37 | Chousuke | and then the runtime will interpret those instructions |
| 03:38 | Chousuke | so when you say main = getLine in haskell, you're saying that the value of main is getLine |
| 03:38 | Chousuke | and when the program executes, it "sees" that the value of main is getLine, and does what it needs to do |
| 03:38 | beaky | how does clojure compare to haskell in expressiveness? I guess clojure wins in that ballpark thanks to dynamic typing and metaprogramming facilities |
| 03:38 | Chousuke | what monads accomplish is allow you to combine two values into one that represents both |
| 03:39 | beaky | or is haskell's magical type system surprisingly expressive? |
| 03:39 | Chousuke | so you can say main = getLine >>= putStrLn |
| 03:40 | Chousuke | which just says "the value of main is the combination of getLine followed putStrLn with the result of getLine" |
| 03:40 | Chousuke | followed by* |
| 03:40 | Chousuke | and that's it |
| 03:40 | mthvedt | yes, and that's what i'm getting at |
| 03:41 | mthvedt | it's dancing around an impedance mismatch, followed by bragging about how neat the dance was |
| 03:41 | Chousuke | mthvedt: there is no impedance mismatch |
| 03:41 | Chousuke | int main() { x = getLine(); putStrLn(x) } says the *exact* same thing |
| 03:42 | tcrayford | beaky: I've never had a problem with expressiveness in either language. Clojure has macros, haskell makes it super easy to write a dsl with free monads/data types. |
| 03:42 | beaky | ah |
| 03:43 | Chousuke | mthvedt: the cool thing in haskell is that it recognises that the operation that combines the two substeps also applies to a lot of other things. |
| 03:43 | Chousuke | for example, callbacks-oriented control flow can be represented as promises |
| 03:44 | Chousuke | and the operations to combine promises... form a monad |
| 03:44 | mthvedt | i know how monads work |
| 03:44 | mthvedt | if that wasn't clear before |
| 03:47 | Chousuke | at any rate, the point is that you don't need monads to do IO, callbacks, or short circuiting evaluation. |
| 03:47 | Chousuke | but since you do all of those things anyway |
| 03:47 | Chousuke | and all of them form monads |
| 03:47 | Chousuke | why would you not use monads? |
| 03:49 | Glenjamin | what's the advantage of doing (do a b) to represent (a >>= b) instead of having the language allow a; b ? |
| 03:50 | beaky | a >>= b is formally recognized by the type system |
| 03:50 | Glenjamin | or i guess, why do i need to know it's a monad |
| 03:50 | mthvedt | that's a good question to ask anyone who's ever done unsafeperformio |
| 03:50 | beaky | once you know that something forms a monad, you can do cool stuff that worked on other monads :D |
| 03:51 | clgv | Glenjamin: good question, e.g. I can use `for` and do not need to know that it is a monad in principle... ;) |
| 03:51 | Glenjamin | i'm ok at basic haskell, but i never really grokked monads - so never done anything more complex than homework assignments |
| 03:51 | Glenjamin | the list monad being some form of nondeterministic search really confused me |
| 03:52 | mthvedt | the other thing is |
| 03:52 | Glenjamin | and then you get into arrows and functors, it often felt like abstraction for abstractions sake |
| 03:52 | mthvedt | should a language really have a high barrier to entry for doing io |
| 03:53 | noprompt | i think it largely depends on what the goals of the language are. |
| 03:53 | Glenjamin | just because everything i do is equivalent to a mathematical model doesn't mean i want to deal with the model most of the time |
| 03:54 | Chousuke | Glenjamin: the nondeterminism is actually not that hard to understand |
| 03:54 | Chousuke | Glenjamin: you can think of a nondeterministic function as one that retuns a list of all its possible outputs |
| 03:54 | mthvedt | in practice, a lot of people don't understand it |
| 03:55 | Glenjamin | i know, but *why* treating lists as monads make them deterministic was lost on me |
| 03:55 | Glenjamin | it was like discovering prolog hidden in the standard sequence container |
| 03:55 | Chousuke | Glenjamin: then combining a nondeterministic function with another means running the other function with every output from the first one |
| 03:55 | Chousuke | and concatenating the result |
| 03:56 | Chousuke | and that operation of combining them is what gives you a monad (along with a return operation) |
| 03:57 | Chousuke | the benefit from treating things as monads generically is that you can write functions that work across all monads |
| 03:57 | Chousuke | and if you have syntactic support for one monad, you have syntactic support for all monads |
| 03:59 | Chousuke | imagine if in C++ you could just do foo (Foo* x) {return x.doSomething()} and if x is null you just get a null. |
| 04:00 | Glenjamin | i don't write in C++, but that seems like how all the high level languages without monads work in that scenario |
| 04:00 | Glenjamin | oh, sorry misread |
| 04:01 | Chousuke | Glenjamin: the thing is, people are adding these things into languages as special cases |
| 04:01 | Chousuke | some languages have .? for null propagation |
| 04:02 | Glenjamin | mm, because you often don't want null to make it further through the computation and blow up when you need a value to do something useful |
| 04:02 | Chousuke | then there are those coffeescript extensions with await and whatnot for less insane node.js programming |
| 04:02 | Chousuke | whereas if you just had a neat syntax for >>=, you'd get all that for free. |
| 04:02 | noprompt | less insane node.js programming? |
| 04:02 | noprompt | not sure if that's saying much. :) |
| 04:02 | Chousuke | noprompt: avoiding nested callbacks |
| 04:03 | noprompt | Chousuke: yeah, i know what you're refering too. |
| 04:03 | Glenjamin | meh, i like node.js |
| 04:04 | Chousuke | if you coded node in haskell you could just write do { x <- someAsyncOp; y <- anotherAsyncOp; return x+y} |
| 04:04 | Glenjamin | the module loading system and dependency management encourages really small, clean re-usable modules |
| 04:05 | Glenjamin | again, i don't really see that as being leaps and bounds better than async.parallel([someAysncOp, anotherAsyncOp], callback) |
| 04:05 | noprompt | well, there is type safety. which *is* a good thing. |
| 04:05 | Chousuke | whereas in javascript that's like someasyncOp(function(x, err) {if (!err) anotherAsyncOp(x, function...{})}) |
| 04:05 | Chousuke | which is a complete horror |
| 04:05 | Glenjamin | noprompt: like in clojure? |
| 04:06 | Chousuke | glenjamin: oh, I forgot to add a dependency of anotherAsyncOp to x |
| 04:06 | noprompt | javascript is just horrific in general. you have to be armed to the teeth with a body of knowledge before you can even consider writing serious code in the language. |
| 04:07 | Glenjamin | again, i don't really see that as being leaps and bounds better than async.waterfall([someAysncOp, anotherAsyncOp], callback) |
| 04:07 | Chousuke | Glenjamin: yeah, and that's a monad |
| 04:07 | Glenjamin | noprompt: i don't strongly disagree, but to do web work you have to know it pretty well |
| 04:07 | noprompt | it's probably the second or third worst language i've used (php being the first). |
| 04:07 | Glenjamin | Chousuke: right, but does knowing its a monad change anything? |
| 04:07 | Chousuke | Glenjamin: you're just using a non-generic implementation of the exact same thing |
| 04:07 | Glenjamin | yes, i agree |
| 04:07 | Chousuke | Glenjamin: and you don't get syntactic benefits |
| 04:08 | noprompt | Glenjamin: well yes if you write raw javascript. |
| 04:08 | Chousuke | do notation is better than what you wrote. |
| 04:08 | Glenjamin | but is it much better? |
| 04:08 | Chousuke | it is. |
| 04:09 | Chousuke | because it's based on something generic, and thus extends to things you can't even imagine yet. |
| 04:09 | Chousuke | like, say, the Tardis monad :P |
| 04:09 | Chousuke | (which is a combination of state and reverse state) |
| 04:09 | noprompt | Chousuke: you're making want to pick up haskell again. :) |
| 04:10 | noprompt | *making me |
| 04:10 | Chousuke | it's unfortunate that Monads are called monads |
| 04:10 | Glenjamin | they should reall be Monoids! |
| 04:11 | Chousuke | if they were called "generic API for boilerplate" people might not be so scared |
| 04:11 | Glenjamin | what's that phrase now... |
| 04:11 | Glenjamin | monads are just monoids in the category of endofunctors |
| 04:11 | Chousuke | yeah, heh |
| 04:11 | mthvedt | i only program in the lambda calculus on categories |
| 04:11 | mthvedt | everything is a category |
| 04:12 | Glenjamin | i'm not especially scared of them, it's just i'm unconvinced of the improvement - you still have to understand what the properties of the monad you're using are in order to compose them |
| 04:12 | Chousuke | Glenjamin: there are a lot of big words in that sentence but what is actually says is really simple :P |
| 04:12 | Chousuke | Glenjamin: sure, but you're doing that anyway when you're working with any kind of data |
| 04:13 | Glenjamin | yep, but more concrete abstractions designed for the particular problem can make the tasks you're likely to do easier |
| 04:13 | Chousuke | I've never seen an example of that |
| 04:13 | noprompt | Glenjamin: you know it's funny you mention that. |
| 04:13 | Glenjamin | and you could build them out of monads, or something less general - but when i'm using the specialised version it stops mattering |
| 04:14 | Chousuke | Glenjamin: I mean, you can do things with specialised versions and it's easy |
| 04:14 | Chousuke | but using the non-special versions is easy too |
| 04:14 | Chousuke | it's just two operators :| |
| 04:14 | Chousuke | and one of them is trivial |
| 04:15 | noprompt | personally, i think people tend to looking to apply general solutions or patterns when building software that they actually miss out on what they're actually trying to do. |
| 04:15 | Chousuke | it's like you'd rather have listSort() mapSort() vectorSort() all separate so that you know what you're sorting each time :P |
| 04:16 | Chousuke | noprompt: I don't think monads are like that |
| 04:16 | Glenjamin | thats why we have interfaces, or protocols / type classes |
| 04:16 | noprompt | Chousuke: i don't necissarily either. |
| 04:16 | Glenjamin | the monad stuff is at a level of abstraction I don't often need to deal with |
| 04:17 | Chousuke | Glenjamin: you're dealing with it all the time |
| 04:17 | Glenjamin | and yet I don't know I am! |
| 04:17 | Glenjamin | which is my entire point |
| 04:17 | Chousuke | Glenjamin: if you knew, you'd stop repeating yourself :) |
| 04:17 | noprompt | i guess what i notice is that people learn about a X design pattern or X abstraction technique and try to make use of it when they really could have just solved their problem with a few lines of code. |
| 04:18 | Glenjamin | That's a monad, I can use the monadic operators / That's some repetition, I can abstract that away |
| 04:18 | Glenjamin | ^^ whats the difference? |
| 04:19 | ejackson | noprompt: i'm not seeing that in myself. As I learn higher level concepts, they dissolve the lower level ones. But its taking a long time. |
| 04:19 | noprompt | iow i can sympathize with what Glenjamin is saying. |
| 04:19 | Chousuke | monads are just a generic operator for the boilerplate in the following: A -> (operation) -> (boilerplate) -> B |
| 04:19 | noprompt | ejackson: i wasn't refering to a large body of people, but some do approach software in this manner. |
| 04:20 | ejackson | fancy composition operators :) |
| 04:20 | Glenjamin | so is A -> (high-level-operator) -> B |
| 04:20 | Chousuke | Glenjamin: that doesn't work if the operator doesn't actually return B |
| 04:20 | noprompt | i worked with a guy a while back who was just so obsessed with "patterns" that it drove me to quit working with him. |
| 04:20 | ejackson | noprompt: oh, sorry, I thought you were making a general argument against higher level abstractions |
| 04:20 | ejackson | noprompt: hehe, I know what you mean now :) |
| 04:20 | Chousuke | Glenjamin: it's just so obvious to me. |
| 04:21 | Chousuke | Glenjamin: if you have functions that can return null, you can just go foo(bar(something(A))) to get B |
| 04:21 | Chousuke | you have to do null checks after everything |
| 04:21 | Chousuke | which is just boilerplate that you can't avoid |
| 04:21 | Glenjamin | (cond-> A something bar foo) |
| 04:22 | Chousuke | that's just one case |
| 04:22 | noprompt | ejackson: i guess my point was that it's important to know when and where to apply abstraction. |
| 04:22 | Glenjamin | it's the case of hiding null |
| 04:22 | Chousuke | Glenjamin: if you have monads and syntactic support for it, you don't need any such special operators. |
| 04:22 | noprompt | of course, i still struggle with that too :) |
| 04:23 | Glenjamin | if you have macros and syntactic support for them, you don't need any such special monads? |
| 04:23 | Chousuke | macros don't compose |
| 04:24 | Glenjamin | mm, thats true |
| 04:24 | Chousuke | what if you had async operations that could return nulls? |
| 04:24 | Chousuke | if you implemented these things as monads, you could still use do syntax |
| 04:25 | Glenjamin | but what if i want to evaluate in parallel, or do something other than chain the calls? |
| 04:25 | Glenjamin | surely i still need more notation |
| 04:25 | Chousuke | Glenjamin: do notation doesn't specify evaluation order |
| 04:26 | Chousuke | other than what is implied by the dependencies of each expression |
| 04:27 | Glenjamin | but if two computations fail in parallel, what error value would i get back? |
| 04:27 | Chousuke | both? it depends on the implementation of your bind |
| 04:27 | Chousuke | that's the point |
| 04:27 | Chousuke | you get to decide what happens |
| 04:27 | Chousuke | but the syntax stays the same |
| 04:28 | Chousuke | there are of course limits to what monads can express |
| 04:28 | Chousuke | but sufficiently many things are monadic that having syntactic support for them is convenient |
| 04:29 | noprompt | the day a language which marry's haskell and lisp comes a long will be a glorious day. |
| 04:29 | Chousuke | I think there is one already |
| 04:29 | Glenjamin | you have convinced me there's an advantage when building composable operations |
| 04:30 | noprompt | Chousuke: there are actually a few i've seen, but they're either no longer maintained or incomplete. |
| 04:30 | Chousuke | Glenjamin: if you think about it, composing things is the majority of what a programmer does nowadays |
| 04:30 | ejackson | Chousuke: so, which is it ? :) |
| 04:31 | Chousuke | Liskell is one I've seen mentioned somewhere |
| 04:31 | Chousuke | I haven't actually looked at it |
| 04:32 | ejackson | do you use Clojure's monads at all ? |
| 04:32 | noprompt | the last i checked liskell wasn't being maintained. |
| 04:32 | noprompt | there's another one called shin. |
| 04:33 | Chousuke | ejackson: I have some code that uses them, and I implemented monads once myself using protocols :P |
| 04:33 | noprompt | sorry, shen. |
| 04:33 | Glenjamin | Chousuke: you've managed to pique my interest enough to try using some monads in my clojure :) |
| 04:34 | Chousuke | ejackson: They're not as ubiquitous in Clojure since having a static type system really helps with monads (gives you safety and all) but you can still get some pretty elegant code |
| 04:34 | Glenjamin | and now I'd better go to work! |
| 04:35 | ejackson | yeah, i hardly ever see them in the wild |
| 04:39 | Chousuke | ejackson: https://gist.github.com/Chousuke/141085 here's some toy code I wrote ages ago to test out clojure monads. I don't think it'd be trivial to write without monads. |
| 04:40 | Chousuke | or rather, you'd just end up duplicating State :P |
| 04:41 | Chousuke | it's a functional parser that supports incomplete input and can be resumed arbitrarily many times. |
| 04:41 | ejackson | that's pretty cool |
| 04:41 | ejackson | and short ! |
| 04:41 | Chousuke | IIRC it has a bug though where the regexp sometimes fails if the input is split in a certain way |
| 04:43 | ejackson | haskell is like malaria: every few years I succumb to a relapse |
| 04:44 | noprompt | ejackson: couldn't have said it better myself! |
| 04:44 | ejackson | i *so* want to actually use it all the time, but haven't put enough block time aside to get it right |
| 04:44 | noprompt | i'm debating picking up either erlang or prolog over the summer. |
| 04:44 | Chousuke | My main problem with haskell is that it makes it more difficult for me to program in other languages |
| 04:45 | ejackson | Clojure has done that to me too |
| 04:45 | Chousuke | "gah why can't I just fmap this and be done" |
| 04:45 | noprompt | Chousuke: yes, and it dooms you to see bugs. |
| 04:45 | ejackson | "what do you mean I can't use vectors as keys in a map, PYTHON ?" |
| 04:45 | ejackson | what's haskells matrix story like ? |
| 04:46 | noprompt | ejackson: clojure reduced ruby to my shell scripting language. |
| 04:47 | noprompt | actually, functional programming in general has ruin my experience in any language that isn't functional. :'( |
| 04:47 | Chousuke | ejackson: I tried doing v = v.sort() in python and then wondered why it wasn't working (I didn't get NPEs because my template-engine silently converted nulls to nothing) |
| 04:48 | noprompt | doomed to obscurity at the local developer meetups. it's a sad life. :) |
| 04:48 | ejackson | yeah, exactly. Clojure teaches you to rely on certain things, and elsewhere they're just not there. |
| 04:48 | noprompt | Chousuke: i had a fun conversation about the relevance of using negative indexes the other day with a python programmer. |
| 04:49 | noprompt | apparently python doesn't even have a last function. |
| 04:52 | noprompt | ejackson: clojure is also a great lesson in thinking in terms of data and data transformation. |
| 06:02 | ayia | Hi guys, How can i "paste" name passed to macro like (defmacro def-name-var [name] ...) into name of the var in its definition, where name should be like -<name>-fields? |
| 06:16 | clgv | ayia: please provide an example macro call and the desired expansion |
| 06:29 | noidi | ayia, maybe you want `symbol`? it takes a string and returns a symbol, so you can do something like `(def ~(symbol (str name "-suffix")) ~value) |
| 06:40 | ayia | clgv: =>(def-name-var jack) ;; should create a var with name -jack-fields |
| 06:40 | clgv | ayia: ok |
| 06:41 | clgv | ayia: (defmacro def-name-var [var-name] `(def ~(symbol (format "-%s-fields" (name var-name))))) |
| 06:43 | ayia | clgv: noidi: thanks you guys, for this approaches... Just one more question, is there any other way to do this, maybe just with using quotes/unquotes? i.e. to make the code even more readable... |
| 06:44 | clgv | ayia: no. you can define a separate function though |
| 06:46 | ayia | clgv: what does this mean "define a separate function"? |
| 06:49 | jaffe_ | ayia: you can define a function that adds the suffix to the symbol, and then have your macro call that function instead |
| 06:51 | clgv | ayia: (defn derive-symbol [fmt s] (symbol (format fmt (name s)))) and then (defmacro def-name-var [var-name] `(def ~(derive-symbol "-%s-fields" svar-name))) |
| 07:00 | ayia | clgv: jaffe_: got it! thanks! |
| 07:56 | beaky | hello |
| 07:56 | knob | Hello! |
| 07:56 | beaky | Rich Hickey often refers to "Polymorphism a la carte" in his speech; what does that mean? |
| 07:56 | beaky | is it like the single-dispatch polymorphism in C++? |
| 08:00 | sparkjoy | I'm not the expert, but my studies so far have revealed both single-dispatch polymorphism |
| 08:00 | joegallo | i think it's like, you can have a slice of cake, or a slice of pie, or also there's multimethods |
| 08:00 | sparkjoy | but also multi-methods |
| 08:01 | sparkjoy | protocols use single dispatch, with a privileged first arg (like this in OO) |
| 08:01 | hyPiRion | beaky: polymorphism as polymorphism itself. It's not bound to classes, only to functions. |
| 08:02 | sparkjoy | multimethods allow you to dispatch based on more than just the first arg |
| 08:02 | sparkjoy | also a very cool thing about protocols |
| 08:03 | sparkjoy | is that you can extend them not only to types that you define |
| 08:03 | sparkjoy | but also to types that others have defined for which you do not control the source |
| 08:04 | sparkjoy | I'm just learning about protocols now (highly recommend _Clojure Programming_) but they sure seem powerful |
| 08:08 | DerGuteMoritz | sparkjoy: note that protocols are just a subset of multimethods |
| 08:08 | beaky | clojure has multimethods too? |
| 08:08 | DerGuteMoritz | yes |
| 08:08 | sparkjoy | yep beaky |
| 08:08 | beaky | (even though it isn't OO at all) :D |
| 08:09 | DerGuteMoritz | protocol methods are just like multimethods which dispatch on the type of the first argument |
| 08:09 | Bronsa | mh, I don't think protocols are exactly a subset of multimethods |
| 08:09 | beaky | so OOP has no monopoly over polymorphism? |
| 08:09 | DerGuteMoritz | well, and with protocols you can also check whether they are implemented for a certain type, not sure if that's possible with multimethods |
| 08:09 | Bronsa | with protocols you can dispatch on the interface too, I don't think you can do that with multimethods |
| 08:09 | DerGuteMoritz | Bronsa: how do you mean? |
| 08:10 | DerGuteMoritz | surely you can use the same dispatch function that's used by protocols? |
| 08:10 | Bronsa | (extend-protocol proto clojure.lang.IPersistentMap (f [this] ..))) |
| 08:10 | DerGuteMoritz | except protocols will be more efficient |
| 08:10 | Bronsa | with a multimethod, you can't do that if you're dispatching on the first argument type |
| 08:11 | DerGuteMoritz | Bronsa: ah, perhaps |
| 08:12 | sparkjoy | beaky: there's plenty of polymorphism in Clojure - you just have finer grained control |
| 08:14 | sparkjoy | watch Rich's "Simple made easy" talk - I think you'll get a feel for his goals of "decomplecting" systems |
| 08:14 | beaky | yeah that was an awesome lecture |
| 08:23 | beaky | so OOP is the enemy of simplicity? |
| 08:24 | sparkjoy | I wouldn't go that far, but I'm knee deep in an enterprise OO system now, using all the best practices, DDD, etc. |
| 08:24 | sparkjoy | and I can tell you that we are not as agile as we could be |
| 08:24 | sparkjoy | in large part because of the silos (classes) we've constructed around our data |
| 08:25 | sparkjoy | we program with immutable objects in C#, and we use immutable, persistent data structures, but this is not idiomatic so we find ourselves fighting against the current a lot |
| 08:26 | sparkjoy | and our persistent data structures suck compared to what's provided by default in Clojure |
| 08:54 | cmajor7 | what would be the way to render protobuf from compojure? overrite "Renderable" with "byte-array" type? |
| 09:18 | stuartsierra | By the way, Hudson releases are (mostly) working again. |
| 09:18 | stuartsierra | In case anyone was waiting to release a library or something. |
| 09:18 | stuartsierra | See my latest email to clojure-dev. |
| 10:12 | dsabanin | hey guys |
| 10:13 | dsabanin | hey guys |
| 10:14 | silasdavis | I'm getting a "don't know how to create ISeq error" which I've learnt usually means I've done somethign weird with '()' |
| 10:14 | silasdavis | could anyone explain how the handler on line 52 could cause this error |
| 10:14 | silasdavis | when the alternative handler/site works fine |
| 10:16 | dsabanin | I wonder what is the right place to put a type hint for return value in defn? before arguments vector or before the name? |
| 10:16 | ucb | silasdavis: paste code? |
| 10:17 | silasdavis | ucb, oh I did paste it, I just didn't give you the link, how helpful of me: https://www.refheap.com/paste/13932 |
| 10:20 | ppppaul | what should i use instead of walk to easily transform a nested data structure? |
| 10:22 | stuartsierra | dsabanin: In the past, functions were type hinted with ^ClassName metadata before the function name. |
| 10:23 | dsabanin | ah, I see. That explains why both ways work :) |
| 10:23 | dsabanin | thanks! |
| 10:23 | stuartsierra | dsabanin: With the introduction of primitive function arguments & return values in Clojure 1.3, you could put return type hints on the argument vector. |
| 10:24 | stuartsierra | ppppaul: If you know something about the structure of the thing you're walking, you can create your own recursive function that will be much more efficient than clojure.walk, e.g. using `update-in`. |
| 10:25 | stuartsierra | clojure.walk is a general, but not very efficient, solution to walking any arbitrary data structure. |
| 10:25 | gfredericks | clojurebot: clojure.walk is a general, but not very efficient, solution to walking any arbitrary data structure. |
| 10:25 | clojurebot | In Ordnung |
| 10:26 | stuartsierra | clojure.walk also doesn't work on `defrecord` types |
| 10:26 | stuartsierra | if I recall |
| 10:27 | tcrayford | also you could try using a zipper. They are super good for walking nested structures and manipulating bits of them as you go |
| 10:27 | ppppaul | stuartsierra, i have found that when i attempt to do transformations with update-in it can get very hairy |
| 10:27 | ppppaul | maybe i'm doing them wrong |
| 10:27 | stuartsierra | Oh, it can get hairy. :) |
| 10:27 | ppppaul | i find my walks to be very simple |
| 10:27 | ppppaul | though, when i need a complicated walk it usually fails |
| 10:28 | ppppaul | so i stack a few simple ones together |
| 10:28 | ppppaul | currently i'm mostly using walks for testing |
| 10:28 | stuartsierra | ppppaul: If it works and is fast enough for the use case, then there's no reason not to use clojure.walk. |
| 10:29 | ppppaul | i think that i can probably get away with memorizing if i need performance |
| 10:29 | ppppaul | thanks stuartsierra, last night there was some talk about walk, and it made me feel like i may be going in the wrong direction with my style of clojure programming |
| 10:30 | stuartsierra | `walk` is certainly convenient - that's why I wrote it. :) |
| 10:32 | ppppaul | i have found it very useful. i even ported it to javascript. |
| 10:36 | ppppaul | actually, since i'm on this topic... stuartsierra there have been occasions where i want to rip out some things from a tree and put them in a flattened array. like maybe all integers or something. i tried to do this a few times with walk but found it extremely hard. do you have any strategy for doing something like that (other than using an atom)? |
| 10:36 | stuartsierra | Yeah `walk` isn't really designed for that. |
| 10:37 | stuartsierra | I do it with recursive functions and `mapcat` but it's not always easy. |
| 10:37 | ppppaul | just wondering if there was some clever way to deal with that with walk... like returning arrays and then doing a flatten or something |
| 10:38 | VFe | Anyone been using Riak via Clojure and have any recommendations for client libs?(i.e. any reason or problems I might encounter using Welle over Sumo or clj-riak, etc) |
| 10:38 | tcrayford | what kinda items are you querying for? You might be able to use tree-seq |
| 10:38 | antares_ | VFe: clj-riak and sumo are not really maintained, AFAIK |
| 10:38 | tcrayford | VFe: I have been. I think welle's the only one of those that is regularly updated |
| 10:38 | ppppaul | hmm... something like #(= (type %) "whatever") |
| 10:38 | tcrayford | (sadly, I don't think welle is very well designed at all) |
| 10:39 | VFe | yeah, welle has been giving me some issues, and I was curious if people used one of the others more regularly |
| 10:39 | antares_ | tcrayford: how many ways are there to design a K/V store API? :) |
| 10:39 | antares_ | VFe: care to elaborate? I'm the author |
| 10:39 | VFe | Oh, well hello :) |
| 10:40 | ppppaul | antares_, redis... |
| 10:40 | tcrayford | antares_: when that store is eventually consistent, there are quite a few things welle does that I'm sad about (I'm a contributer, and using it) |
| 10:40 | antares_ | ppppaul: I'm talking about client libraries |
| 10:41 | ppppaul | hmmm... there are probably a lot of ways to do so |
| 10:41 | antares_ | tcrayford: well, I've seen only one issue from you, what else is missing? |
| 10:41 | antares_ | ppppaul: really? for a key/value store? |
| 10:41 | ppppaul | but the top level API shouldn't be so big |
| 10:42 | VFe | Well, first question, when I run it from repl, am I supposed to see like 3 pages of reflection warnings? |
| 10:42 | antares_ | VFe: welle itself has next to no reflection warnings |
| 10:43 | antares_ | some of its dependencies have them |
| 10:43 | tcrayford | antares_: the api doesn't force people to use resolvers/retriers, and the docs sorta handwave over receiving conflicts. |
| 10:43 | antares_ | tcrayford: and that's it? |
| 10:43 | VFe | yeah, I see nrepl, complete/core, etc, so that's expected behavior then? |
| 10:44 | antares_ | tcrayford: retriers are now used by default. Forcing people to use resolvers sounds a bit too much. |
| 10:44 | antares_ | tcrayford: man, at least we have some documentation. Most projects don't even explain what the hell R, W, DW and so on are. |
| 10:44 | tcrayford | antares_: right. I'm glad about that ;) |
| 10:45 | antares_ | VFe: the only way to solve it is to run after every dependency (and dependency dependency, and so on) and fix reflection warnings there |
| 10:45 | antares_ | people did fix some in Cheshire and clj-http |
| 10:46 | antares_ | sometimes they can't really be avoided, because in Clojure you only can overload on function arity, not types |
| 10:46 | tcrayford | antares_: the fact that I've been wrapping welle in my own library so that the interface is nicer kinda makes me want to just go away and write my own clojure client lib on top of the basho java client. |
| 10:47 | antares_ | tcrayford: well, it's your call :) |
| 10:47 | tcrayford | antares_: I'm not sure, but I think modify might do the wrong thing with vclocks right now as well. Also, I have a rant about the *riak-client* and binding style of injecting the client, but that seems standard in clojure, sadly. |
| 10:48 | antares_ | tcrayford: there is one thing that will change in 1.6 with vclock |
| 10:48 | antares_ | apparently the value we need to propagate is the one from the response |
| 10:48 | antares_ | and it's currently not preserved. So kv/fetch return value will have to change :( |
| 10:49 | tcrayford | antares: is that with modify? That was my issue ;) |
| 10:49 | antares_ | to {:vclock … :object …} |
| 10:50 | antares_ | tcrayford: it affects modify but is also a problem of its own |
| 10:50 | antares_ | unfortunately, the Java client itself has next to no docs |
| 10:51 | antares_ | at least did not have them 2 years ago when Welle was started |
| 10:51 | tcrayford | antares_: that'd cause sibling explosion, right? (assuming you have allow_mult on, which should nearly always be the case) |
| 10:51 | antares_ | so it wasn't obvious which vclock value we have to use |
| 10:51 | tcrayford | antares_: yeah. It's been rewritten completely since then from my perspective ;) |
| 10:51 | antares_ | yes, that's what aphyr has observed |
| 10:51 | antares_ | with his network splits simulation tool |
| 10:52 | antares_ | tcrayford: I didn't see major changes, they just added and documented some stuff |
| 10:52 | tcrayford | heh. It's a good thing the app I've written on top of welle isn't in production yet then ;) |
| 10:52 | antares_ | with this change, I don't think there will be anything missing in Welle w.r.t. to the Java client |
| 10:52 | antares_ | except that you don't have domain objects, of course |
| 10:52 | tcrayford | well, that's part of clojure |
| 10:52 | tcrayford | ;) |
| 10:53 | tcrayford | the shit you store in riak should just be data, not domain objects ;) |
| 10:53 | ieure | Sup tcrayford. |
| 10:53 | tcrayford | ieure: sup |
| 10:54 | antares_ | tcrayford: what I often used Riak for, I often used LWW :) but I hear ya. I think 1.6 will be out in the next few days. We got a lot of tests to update, but the code change is minor. |
| 10:55 | tcrayford | antares_: neat. Thanks. I don't wanna sound pissed off, welle is reasonably good as far as the riak clients I've used go. |
| 10:55 | antares_ | tcrayford: but I totally welcome more clients |
| 10:55 | antares_ | tcrayford: there is #clojurewerkz now if you want to suggest something or complain about welle more ;) |
| 10:56 | tcrayford | antares_: it'll be a while if I do my own, I have an app to ship first |
| 10:56 | antares_ | VFe: not sure if this answers your question, but with 1.6, Welle will likely be good enough even for demanding users. And it is maintained, including the docs. |
| 10:57 | VFe | My main issue was the reflection things, pages of warnings tend to make me think I'm doing something wrong XD |
| 10:57 | antares_ | tcrayford: understandable. If you want to see more changes in Welle, please file an issue. |
| 10:57 | VFe | But the discussion was enlightening, I mainly asked cause I have to decide what we're going to be using in production |
| 10:58 | antares_ | VFe: can you gist them? |
| 10:58 | VFe | sure |
| 10:59 | tcrayford | antares_: honestly most of the changes I'd want to see would be api changes (e.g. I don't think most of the options to fetch/store/etc should be options, they should be bundled up in a "bucket", along with a resolver/retrier. Those are more personal opinion things though. I have an internal namespace that does all of that for me right now). |
| 11:00 | VFe | https://gist.github.com/VFe/5452786 |
| 11:01 | antares_ | tcrayford: Riak Java client kinda has two clients: "raw" and POJO-oriented. We can consider adding a "higher level" one in Welle. |
| 11:01 | tcrayford | antares_: yeah. We should take this discussion to #clojurewerkz, not keep it in here |
| 11:01 | antares_ | VFe: so, most of them are from complete/core. Is that an OSS library? |
| 11:02 | antares_ | VFe: clojure.tools.nrepl I can't fix, I live in a country that has no reliable mail to US, so I won't be filing Clojure CA until it is electronic :( |
| 11:05 | VFe | I actually don't know what complete.core is, though in regards to the second part, couldn't you sign the document, email it to someone you trust in the US, have them print it and send for CA? |
| 11:05 | VFe | i.e. have someone act as your legal proxy |
| 11:06 | antares_ | VFe: it's not a Welle dependency, it's loaded by something else |
| 11:06 | noidi | VFe, if that was acceptable then Rich Hickey could just receive the e-mail directly and print it out himself if he ever needs a copy |
| 11:07 | antares_ | VFe: possibly. I don't generally bother with core.* stuff, even trivial patches are accepted 3-12 months after you submit them. |
| 11:07 | antares_ | that's not how OSS should work and I'm tired of trying to change the system. There are better ways to spend time. |
| 11:08 | antares_ | nrepl developers are a bit better in this regard |
| 11:08 | beaky | hello |
| 11:09 | antares_ | VFe: if you run lein deps :tree, it should show you what dependencies you have. Could you please gist that? |
| 11:09 | beaky | how do I run clojure programs on my platform? I am using archlinux on x86/64 |
| 11:09 | nDuff | antares_: Can you send faxes? Those are legally recognizable in the US in many cases (Relevance would have to talk to their lawyer, which I'm not, to determine if that's the case here). |
| 11:09 | VFe | lol, I like how I I just googled for complete/core/clj and now that gist is on first page of results |
| 11:10 | VFe | I suddenly feel so alone |
| 11:10 | VFe | and yeah, lemme do that |
| 11:10 | noidi | beaky, do you want to get started with Clojure development, or run a program written by someone else in Clojure? |
| 11:10 | beaky | get started :D |
| 11:11 | antares_ | beaky: there are tutorials at http://clojure-doc.org, take a look |
| 11:11 | beaky | ah thanks |
| 11:11 | beaky | hmm clojure uses square brackets and braces too... thats new :D |
| 11:12 | antares_ | nDuff: the policy is, you mail a piece of paper or sign it at one of the Relevance events. And then there are "screeners" and Clojure/core and months and months of waiting. I won't bother with that. |
| 11:12 | nDuff | antares_: Yes, I know -- I've done the "sign it at a conj" thing. |
| 11:12 | VFe | https://gist.github.com/VFe/5452872 |
| 11:12 | nDuff | antares_: ...but I'm saying that it should be possible to make a case for accepting faxes. |
| 11:12 | beaky | btw why does it use first/rest instead of car/cdr? |
| 11:12 | technomancy | heh; faxes |
| 11:13 | antares_ | nDuff: the process is made intentionally hard. I'm not going to cooperate. |
| 11:13 | nDuff | technomancy: They're used for sensitive medical documents all the bloody time. |
| 11:13 | antares_ | beaky: because nobody knows what car/cdr mean |
| 11:13 | technomancy | http://achewood.com/index.php?date=11222006 |
| 11:13 | nDuff | antares_: Ahh. If it's protest, that's a completely different matter. |
| 11:13 | antares_ | beaky: besides CL and Scheme users, which are a tiny % of people who get into Clojure (33% Java, 33% Ruby/Python) |
| 11:13 | beaky | yeah I guess it's car/cdr are way too oldschool/archaic and first/rest are more communicative |
| 11:14 | VFe | Technically, in the US, signature is an intent, which is why anything can be a signature, including digital. or why you can proxy your legal rights at will. |
| 11:14 | antares_ | nDuff: not really a protest, I just don't think it's worth it |
| 11:14 | VFe | So if they don't accept an email or fax, its a matter of personal policy, not of legality |
| 11:14 | noidi | besides, clojure's sequences are not linked lists made out of cons cells |
| 11:14 | ieure | beaky, Clojure takes some inspiration from Scheme, which uses first/rest rather than car/cdr. |
| 11:14 | noidi | so car/cdr could lead old lisp programmers astray in thinking that |
| 11:14 | tcrayford | antares_: I haven't signed one as well, for similar reasons. I've been to relevance events and not signed purposefully. |
| 11:14 | beaky | so the default clojure sequence is something from java? |
| 11:15 | tcrayford | no |
| 11:15 | ieure | Well. |
| 11:15 | ieure | Much of Clojure is implemented in Java, or at least has Java interfaces. |
| 11:15 | noidi | beaky, http://clojure.org/sequences |
| 11:15 | beaky | I am only familiar with C++ :D |
| 11:15 | ieure | So clojure.lang.ISeq is the underlying type. |
| 11:15 | beaky | ah thanks |
| 11:16 | antares_ | beaky: please read a guide on sequences at http://clojure-doc.org, they are not implemented as cons cells and yes, they are implemented in Java. But most importantly they are immutable. |
| 11:17 | antares_ | beaky: a slightly more approachable version http://clojure-doc.org/articles/language/collections_and_sequences.html |
| 11:17 | beaky | ah, so clojure sequences are much like haskell's [] |
| 11:18 | beaky | but more general |
| 11:18 | tcrayford | well, haskell |
| 11:18 | lucian | beaky: or less general, depending how you look at it |
| 11:18 | tcrayford | 's [] is implemented as cons cells iirc |
| 11:18 | lucian | beaky: certainly more explicit |
| 11:18 | beaky | ah |
| 11:18 | beaky | that's awesome |
| 11:19 | beaky | I like the idea of having a uniform interface for sequences |
| 11:19 | maio | I would like to serve result of write function from https://github.com/jkk/purty/blob/master/src/jkkramer/purty.clj as HTTP response. Any idea how to do that? It expects something that works with clojure.java.io/file |
| 11:19 | beaky | e.g. in C++, the containers are unified under iterators |
| 11:19 | beaky | (but C++ containers are mutable by default) :( |
| 11:19 | tcrayford | beaky: haskell has uniform interfaces for sequences (see Traversable/etc). They're just not commonly used |
| 11:21 | beaky | hmm why not? :( |
| 11:21 | beaky | maybe the haskell crowd prefers pointfree or something else I guess |
| 11:22 | tcrayford | for one thing they're kinda complicated interfaces, and they're not exported by the Prelude. First/Rest is a much better design (imo) |
| 11:22 | beaky | ah |
| 11:23 | beaky | seq is simple yet powerful :D |
| 11:29 | tomoj | Traversable > Seq |
| 11:29 | beaky | is there a nice repl with autocomplete for clojure? |
| 11:30 | vijaykiran | beaky: nrepl has autocomplete |
| 11:30 | cmajor7 | answering my own question (serving protobuf from Compojure). no need to extend "Renderable", just wrap it into ByteArrayInputStream. |
| 11:31 | nDuff | beaky: I'm very happy with emacs' nrepl.el |
| 11:31 | cmajor7 | beaky: "lein repl" |
| 11:31 | beaky | ah |
| 11:32 | beaky | lein repl works :D |
| 11:32 | beaky | I think ill try nrepl |
| 11:32 | beaky | im a vim user... how long will it take me to ge tused to emacs? :D |
| 11:34 | technomancy | don't learn emacs and clojure at the same time |
| 11:34 | antares_ | beaky: why not use Vim Fireplace? |
| 11:35 | antares_ | beaky: http://clojure-doc.org/articles/tutorials/vim_fireplace.html |
| 11:35 | TimMc | Is clojure-jack-in still a thing? |
| 11:35 | beaky | ah thans |
| 11:35 | TimMc | I installed clojure-mode from Marmalade, but that command is missing. |
| 11:36 | tcrayford | beaky: vim is fine with clojure. Not as fluid as emacs, but fine. Fireplace has some weird redrawing bugs on my system, but nothing super bad |
| 11:37 | beaky | :D |
| 11:37 | blrm | beaky: vim fireplace is nice. I did wind up switching to emacs just for clojure, and it wasn't so bad. But yeah, learning clojure and a new editor at the same time is not going to be fun |
| 11:37 | rbxbx | tcrayford: beaky fwiw I've found vim/fireplace better in some regards than nrepl.el (if you'll pardon the heresy) |
| 11:37 | beaky | I always thought of emacs as the ultimate lisp ide |
| 11:37 | kliph | I seem to remember stumbling upon a MIT Scratch/Berkeley BYOB visual block-based programming implementation in Clojure, but now I can't find it. Am I off my rocker or can anyone point me in the right direction? |
| 11:39 | tcrayford | rbxbx: it also has the bit in the readme about tim TPing your house |
| 11:40 | blrm | beaky: you might check out emacs live if you decide you want to learn emacs. that helped me to get started with emacs+clojure: https://github.com/overtone/emacs-live |
| 12:06 | beaky | if clojure is not object-oriented at all, how does it do interop with java? |
| 12:06 | beaky | (which is pretty religious about OOP) :D |
| 12:07 | danlarkin | clojure lets you invoke methods on objects |
| 12:07 | beaky | ah |
| 12:07 | danlarkin | and do other stuff too, like implement interfaces and inherit from classes, but that's generally not necessary |
| 12:08 | mikerod | I'm looking at the source for `reify` and I see that it is a macro. It uses a function `reify*`. Where is `reify*` defined at? I can't seem to find it. |
| 12:09 | mikerod | In the clojure source that is. |
| 12:09 | llasram | mikerod: It's a special form, directly recognized by the compiler |
| 12:09 | nDuff | mikerod: clojure/lang/Compiler.java |
| 12:10 | mikerod | Ah, ok. I didn't realize this. Thank you. |
| 12:11 | joegallo | lo, in the beginning there were the special forms, and the special forms were with clojure, and the specials forms were clojure. |
| 12:12 | mikerod | :) |
| 12:12 | antares_ | mikerod: special forms are listed on http://clojure-doc.org/articles/language/macros.html#special_forms :) |
| 12:15 | mikerod | antares_: Oh, I have not came across this one before. That's a great reference, thanks. |
| 12:29 | jcromartie | so here's a weird question |
| 12:29 | jcromartie | what's should I name a ref that holds the state of the data model |
| 12:29 | jcromartie | in a local scope |
| 12:30 | jcromartie | "ref" is already core/ref |
| 12:30 | jcromartie | "model" sounds more like a value |
| 12:30 | jcromartie | same with "state" |
| 12:31 | antares_ | jcromartie: state is fine (and pretty common). You can also use ref'. |
| 12:31 | jcromartie | but then I use "state" to name the current value in the function arguments to alter, send, etc. |
| 12:33 | jcromartie | and Clojure calls the current value of an identity/ref "state" |
| 12:33 | bbloom | jcromartie: i've run into that naming conundrum before... where you have like the-state and a-state |
| 12:33 | beaky | how does clojure achieve encapsulation without OOP? |
| 12:33 | Ember- | via several means but also encapsulation isn't as important as with OOP |
| 12:33 | jcromartie | beaky: closures, records, datatypes |
| 12:34 | jcromartie | beaky: you shouldn't worry about hiding things, but you should try to abstract things |
| 12:34 | Ember- | if you have no mutable state then a large part of why encapsulation is so crucial with OOP goes out of the window |
| 12:34 | beaky | ah |
| 12:35 | bbloom | jcromartie: i've more or less just decided it's ok to shadow the ref's name |
| 12:37 | bbloom | jcromartie: (defmacro swapping! [name & body] `(swap! ~name (fn [~name] ~@body))) |
| 12:37 | bbloom | i've never actually used that, but it conveys a pattern :-P |
| 12:37 | jcromartie | nice |
| 12:37 | beaky | so in clojure, all the OOP fluff is simply unnecessary? :D |
| 12:37 | bbloom | beaky: no one said that |
| 12:37 | beaky | ah |
| 12:38 | bbloom | beaky: OOP is a deeply understood and well studied bag of tools |
| 12:38 | bbloom | beaky: clojure just embodies the opinion that OOP is the wrong default |
| 12:41 | ToBeReplaced | anyone have any tools for edn-based rpc they like? |
| 12:41 | beaky | it's not the default because it ties together a bunch of stuff in an unnatural way? |
| 12:41 | technomancy | ToBeReplaced: sure: https://github.com/technomancy/die-roboter |
| 12:41 | bbloom | beaky: great talk by stuartsierra on thinking in data instead of objects: http://www.infoq.com/presentations/Thinking-in-Data |
| 12:41 | beaky | ah thanks |
| 12:43 | jcromartie | but at some point you might need something object-like (i.e. an identity that changes) |
| 12:43 | jcromartie | for instance a cache of values that is updated in the background |
| 12:43 | bbloom | jcromartie: objects are useful even without identities sometimes |
| 12:45 | bbloom | jcromartie: like take a look at clojure/zip.clj, which rich wrote in the early days of clojure |
| 12:45 | jcromartie | bbloom: what would that be? isn't it just data at that point? |
| 12:45 | jcromartie | ah |
| 12:45 | bbloom | jcromartie: it stores functions in the metadata of a vector.... |
| 12:45 | bbloom | jcromartie: it would probably have been much better as a protocol & a reify |
| 12:46 | bbloom | (but i don't think those existed at the time) |
| 12:46 | jcromartie | nope |
| 12:46 | bbloom | objects are great when you have "co-data"... aka data that isn't printable/readable/immutable/acyclic/etc |
| 12:46 | bbloom | see also seqs |
| 12:47 | bbloom | they use objects to represent infinite data, not identities |
| 12:49 | ToBeReplaced | technomancy: cool, but not what i'm looking for; i'm looking for libraries to handle the equivalent of the json-rpc spec with edn |
| 12:49 | technomancy | ToBeReplaced: hm. never used json-rpc, but if there are no libraries for it, it could be because it's just a trivial compojure handler |
| 12:51 | ToBeReplaced | yeah it's pretty straight forward / easy to roll -- you want the same kind of thing for client too |
| 12:51 | beaky | (alter-var-root #'*read-eval* (constantly false)) ;; What does this line do? It was generated by lein and it says it somehow prevents some kind of dangerous behavior |
| 12:56 | no7hing | it prevents the clojure reader from evaluating forms that were e.g. loaded via slurp |
| 12:57 | antares_ | beaky: disables evaluation of arbitrary code by the reader (clojure.core/read-string, etc) |
| 12:57 | antares_ | beaky: if you use Clojure 1.5.1, it is the default so that line can be removed |
| 13:02 | andyfingerhut | beaky: antares_: *read-eval* still defaults to true in Clojure 1.5.1 |
| 13:03 | antares_ | andyfingerhut: oh |
| 13:03 | beaky | ah |
| 13:03 | andyfingerhut | Clojure 1.5.1 added the clojure.edn/read and read-string functions, that behave much like clojure.core/read and read-string, except have no ability to execute code as a side effect. |
| 13:04 | andyfingerhut | tools.reader contrib library also provides similar capability for edn reading with no side effects, and works with Clojure 1.3 and later. |
| 13:04 | andyfingerhut | clojure.core/read has its uses as it is still, but primarily when you want to pass around executable Clojure code as text. |
| 13:16 | technomancy | beaky: it was meant to be a workaround for the problem that read and read-string were unsafe on user-provided data, but they changed the tune and said that they now aren't intended for user data anyway |
| 13:17 | technomancy | which IMO is unhelpful because they are still going to be used for it anyway, but that ship has sailed |
| 13:22 | sritchie | cemerick, any advice on how to get clj-http to provide a proper csrf header in a post request? |
| 13:30 | mynomoto | How do I require a project namespace in a lein plugin? |
| 13:31 | technomancy | mynomoto: eval-in-project |
| 13:31 | technomancy | that is, leiningen.core.eval/eval-in-project |
| 13:31 | mynomoto | technomancy: I tried that, but not sure how to use it. Do you have an example? |
| 13:33 | technomancy | mynomoto: sure; see the source for the "check" task in leniingen |
| 13:33 | mynomoto | Ok, thanks. |
| 13:34 | technomancy | basically it's like eval except it takes a project argument first |
| 13:34 | technomancy | project map |
| 13:37 | cemerick | sritchie: you mean something like X-Requested-With? |
| 13:37 | sritchie | cemerick: figured it out -- I just needed to use the :cookie-store option |
| 13:37 | cemerick | ah |
| 13:38 | cemerick | sritchie: yeah, X-Request-With isn't right, anyway. |
| 13:39 | silasdavis | how should I convert ':foo' to 'foo'? |
| 13:39 | llasram | Do you want ##(name :foo) ? |
| 13:39 | lazybot | ⇒ "foo" |
| 13:40 | silasdavis | thanks |
| 13:43 | Glenjamin | when the 'check' task warns about reflection, what is it actually warning about? |
| 13:45 | technomancy | ...is this a trick question? |
| 13:55 | beaky | does a dynamically-typed programming language need polymorphism? |
| 13:56 | technomancy | beaky: you need polymorphism for clojure's built-in types. genuine need for polymorphism for user-defined types is fairly rare. |
| 13:57 | technomancy | it's completely orthogonal to the static/dynamic divide though |
| 13:57 | beaky | ah |
| 13:58 | patchwork | Trying to wean myself off swank for nrepl |
| 13:59 | patchwork | Can you embed nrepl inside a running process? |
| 13:59 | beaky | what are clojure's builtins? I guess it has strings, symbols, singly-linked lists, vectors, hashmaps, and sets? |
| 13:59 | technomancy | patchwork: yeah, it's in the nrepl readme |
| 14:00 | patchwork | technomancy: I read through it, I just see it being able to start from the command line or from within emacs, but nothing about starting it from inside my app then connecting to it |
| 14:01 | technomancy | patchwork: are you sure you have the right readme? |
| 14:01 | patchwork | That is the main draw for swank, I can start it up inside my app then control my running app process from emacs |
| 14:01 | patchwork | https://github.com/kingtim/nrepl.el ? |
| 14:01 | technomancy | https://github.com/clojure/tools.nrepl |
| 14:01 | technomancy | you're reading the client's readme, not the server |
| 14:01 | patchwork | technomancy: Aha, thanks! |
| 14:01 | technomancy | sure |
| 14:03 | jcromartie | I really need to get out of this one-big-ref thing |
| 14:03 | jcromartie | I have one ref for the configuration of the app |
| 14:03 | patchwork | jcromartie: I just went through that |
| 14:04 | jcromartie | but then the runtime data should have its own references |
| 14:04 | jcromartie | atoms, agents, whatever |
| 14:04 | jcromartie | I have an API that is used by a JS front-end for making changes to the config. |
| 14:04 | patchwork | I think it is better to have a dynamic var actually, then you can rebind it at will, but not affect other processes |
| 14:04 | patchwork | you bind it when the app boots |
| 14:04 | jcromartie | I think I might just do that |
| 14:04 | jcromartie | because I don't realyl need to create instances of the system |
| 14:05 | jcromartie | I went down this route thinking it was cool |
| 14:05 | patchwork | I ran into trouble with the ref because all threads saw the same thing! |
| 14:05 | patchwork | It is helpful if that is what you want |
| 14:05 | beaky | can you program in an imperative style in clojure? (like in scala) |
| 14:05 | patchwork | but for config I needed to change some options |
| 14:05 | jcromartie | beaky: sure why not? |
| 14:05 | patchwork | beaky: If you insist! |
| 14:05 | patchwork | (do (op! …) (op! …) ...) |
| 14:06 | beaky | ah :D |
| 14:06 | jcromartie | patchwork: someone gave me the idea of having a function that creates a "system" ref that can be held in the REPL or whatever and then pass that to functions that create compojure handlers etc |
| 14:06 | jcromartie | but it would just be simpler to have a var |
| 14:06 | patchwork | jcromartie: I found the var to be more flexible for config specifically |
| 14:07 | jcromartie | and you can add watches to save it etc |
| 14:07 | patchwork | but I'm sure others have other opinions! |
| 14:07 | jcromartie | I dunno |
| 14:07 | jcromartie | I'd just have a ref in a var |
| 14:07 | jcromartie | I have a good system in place for persistence |
| 14:07 | patchwork | Do you know about the #'var-name idiom? |
| 14:07 | jcromartie | yes |
| 14:08 | patchwork | it returns a reference to the var, not the value |
| 14:08 | patchwork | very useful |
| 14:08 | jcromartie | it just returns the var itself |
| 14:09 | patchwork | Yeah. I avoid dynamic vars everywhere (it couples code too heavily and fns can't be reused elsewhere), but config needs user specified values somehow |
| 14:12 | Glenjamin | is there a quick way to grab the first non-empty string in a sequence? |
| 14:12 | tcrayford | (first (filter empty? seq)) |
| 14:12 | tcrayford | oh |
| 14:12 | tcrayford | non empty |
| 14:12 | patchwork | Glenjamin: (first (filter identity seq)) |
| 14:13 | patchwork | Or more clearly (first (remove empty? seq)) |
| 14:13 | tcrayford | ,(first (filter (complement empty?) ["a" ""]) |
| 14:13 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 14:13 | patchwork | remove/filter are lazy so it will only calculate up to the first non-empty string |
| 14:13 | tcrayford | ,(first (filter (complement empty?) ["a" ""])) |
| 14:13 | clojurebot | "a" |
| 14:14 | kaw | patchwork: Isn't "" trueish? |
| 14:14 | Glenjamin | presumably that identity one doesn't work, or i could just use (or) |
| 14:14 | tcrayford | yeah, identity doesn't work |
| 14:14 | tcrayford | filter is fine because of laziness though |
| 14:14 | patchwork | Ah, yeah I was thinking nil, not "" |
| 14:15 | tieTYT2 | http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class |
| 14:15 | Glenjamin | it's a shame clojure doesn't have a haskell style function composition operator |
| 14:15 | tcrayford | comp is ok |
| 14:15 | tcrayford | clojure doesn't have operators! |
| 14:16 | Glenjamin | hah, true |
| 14:16 | Glenjamin | reader macro then :p |
| 14:16 | tcrayford | like arc? |
| 14:16 | tcrayford | (a:b thing) |
| 14:16 | Glenjamin | that could work |
| 14:18 | bbloom | blargh. just what i need. yet another thing that breaks * and # in vim |
| 14:18 | Glenjamin | ,((comp first remove) empty? ["" "a"]) |
| 14:18 | clojurebot | "a" |
| 14:18 | Glenjamin | vs |
| 14:18 | Glenjamin | ,(first (remove empty? ["" "a"])) |
| 14:18 | clojurebot | "a" |
| 14:19 | Glenjamin | or i guess (-> ["" "a"] (remove empty?) first) |
| 14:19 | Glenjamin | ,(-> ["" "a"] (remove empty?) first) |
| 14:19 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$empty_QMARK_> |
| 14:19 | Glenjamin | bah, ->> |
| 14:19 | Glenjamin | anyway, it all seems to be roughly the same size-wise |
| 14:26 | gfredericks | woah that money library has functions called `plus` and `minus` o_O |
| 14:27 | antares_ | gfredericks: yes, what about it? |
| 14:28 | antares_ | we used the same names as Joda Money. Also, asking people to :refer-clojure :except [+ -] is a bit too much |
| 14:29 | gfredericks | antares_: I'd rather do :as m with m/+ and m/- |
| 14:30 | antares_ | gfredericks: then our + would be non-variadic |
| 14:30 | Raynes | antares_: Please, please expect that people are going to :require :as your libraries. |
| 14:30 | antares_ | at least if we change the signature |
| 14:30 | antares_ | Raynes: I am not recommending :use or :refer :all |
| 14:31 | Raynes | I'd so much rather have then called + and - and have to qualify them. |
| 14:31 | Raynes | them* |
| 14:31 | tcrayford | (money/+ a b) reads worse than (money/plus a b) to me |
| 14:32 | antares_ | I followed joda money names, it doesn't matter to me if it is + or plus |
| 14:32 | Raynes | I mean, it isn't a huge deal, but clj-time is super inconsistent because it's horrified of shadowing clojure.core names. |
| 14:32 | antares_ | plus does not behave like clojure.core/+ if you take a close look |
| 14:32 | antares_ | it is not variadic, it can accept Java objects or doubles |
| 14:32 | llasram | I'd like it to be `+` please (Unicode "PLUS SIGN" character) |
| 14:33 | Raynes | Shadowing doesn't imply behaving the same. |
| 14:33 | antares_ | Raynes: may also be because it is really old and has dozens of functions in a single namespace |
| 14:33 | trinary | use the emoji fat plus |
| 14:33 | gfredericks | tcrayford: because of the '/' and the '+' next to each other? |
| 14:33 | antares_ | trinary: ha |
| 14:33 | Raynes | plus and minus are perfectly acceptable in any case. |
| 14:33 | tcrayford | gfredricks: yep |
| 14:33 | tcrayford | also |
| 14:33 | tcrayford | does money// even work? |
| 14:33 | tcrayford | for division? |
| 14:34 | antares_ | good point, amounts// would at least look terrible |
| 14:34 | antares_ | tcrayford: it should |
| 14:34 | Raynes | &(clojure.core// 10 2) |
| 14:34 | lazybot | ⇒ 5 |
| 14:34 | tcrayford | there's something new about clojure's syntax |
| 14:34 | tcrayford | (to me) |
| 14:34 | gfredericks | is that // bug fixed? |
| 14:34 | antares_ | lets call division // to confuse people! |
| 14:35 | antares_ | I still roll my eyes when I have to use =:= and =/= in Erlang |
| 14:36 | Raynes | I roll my eyes when I have to use ports in Erlang. |
| 14:37 | gfredericks | in any case, I think most would agree that the idiomatic clojure practice is to give things the most straightforward name and use namespaces to distinguish |
| 14:38 | gfredericks | then the user can decide if they want naked symbols to refer to the core version or the library version or whatever |
| 14:38 | Raynes | We should put it in that monstrous style guide! |
| 14:38 | antares_ | gfredericks: I thought the most idiomatic is to be all anal about consistency? |
| 14:39 | gfredericks | antares_: I'm not sure what you mean by that |
| 14:39 | Raynes | Yeah, that's a horrible thing to be. |
| 14:39 | antares_ | when a minor difference in behavior with clojure.core/+ means you have to pick a different name :) |
| 14:39 | gfredericks | oh I see |
| 14:39 | Raynes | After you've used clj-time for more than five seconds and ended up in secs seconds second minutes mins minute hell... |
| 14:40 | gfredericks | no, I agree with raynes that using the same name doesn't imply any particular similarity; also is there some reason it can't be variadic? |
| 14:40 | Raynes | FWIW, I'm totally fine with plus and minus. |
| 14:40 | Raynes | I was just making a case for not avoiding shadowing in other scenarios. |
| 14:41 | antares_ | Raynes: I think clj-time is a case where the domain is very nuanced, less so with money. There are "hours" and "hours of day", for example, the former is a period of time |
| 14:41 | Raynes | antares_: Not what I mean though. |
| 14:41 | Raynes | antares_: IIRC, there is at least one case where it names something 'sec' instead of 'second' because of clojure.core/second, while the minute analogue is called 'minute'. |
| 14:41 | Raynes | That is *horrifying*. |
| 14:42 | Raynes | And I've nearly broken things over it in the past. :P |
| 14:42 | antares_ | Raynes: maybe I focused to much on seconds vs second vs secs :) |
| 14:42 | callen | why isn't it days/hours/minutes/seconds |
| 14:42 | gtrak | &min |
| 14:42 | lazybot | ⇒ #<core$min clojure.core$min@11cdd43> |
| 14:42 | antares_ | Raynes: please file an issue, I think seancorfield would consider changing that to "second" |
| 14:43 | Raynes | I doubt it. It'd be a breaking change. |
| 14:43 | antares_ | I doubt clojure.core/second gets much use |
| 14:43 | gfredericks | I use it all the time |
| 14:43 | gfredericks | but the shadowing wouldn't bother me, obviously |
| 14:43 | antares_ | callen: there are functions that return a period of N seconds and # of seconds on a date/time |
| 14:43 | antares_ | Raynes: it's OK to have a breaking change once in a few years |
| 14:43 | antares_ | I'm going to break a few key functions in Welle tomorrow :) |
| 14:44 | Raynes | antares_: So, you do some Erlang? |
| 14:44 | antares_ | because it's the right thing to do |
| 14:44 | antares_ | gfredericks: fortunately, it's not Ruby, people will get a warning |
| 14:44 | gtrak | make a new lib called clj-time+ or clj-time-plus |
| 14:44 | gfredericks | antares_: oh sure |
| 14:44 | antares_ | Raynes: yes, mostly on and around RabbitMQ. Also have an Elixir library :) |
| 14:44 | VFe | the real question I have, is how do I actually use emoji in clojure?! (defn 🍉 [🐉 🐪 💀](+ (* 🐪 🐉) 💀)) |
| 14:44 | antares_ | gtrak: noooooo |
| 14:44 | Raynes | antares_: https://www.refheap.com/paste/13920 I'll pay you $10 to send Erlang a patch for this. |
| 14:45 | Raynes | Of course I'm pretty sure that involves C. |
| 14:45 | antares_ | VFe: like so twitter.com/michaelklishin/status/270072723751960576? ;) |
| 14:45 | antares_ | Raynes: I don't hack on OTP, I use Erlang |
| 14:45 | Raynes | antares_: But you should. |
| 14:46 | gfredericks | using words for numeric operations bothered the hell out of me every time I wanted to do alternative arithmetic in java or JS; clojure allows that to be much nicer in my opinion |
| 14:46 | gfredericks | but I don't mind being a minority on that. I can always creating locals for + - * / etc :) |
| 14:46 | antares_ | Raynes: right after clojurewerkz passes 100 projects, I promise |
| 14:46 | gfredericks | (defmacro with-money-math ...) |
| 14:46 | technomancy | gfredericks: CL's use of -p for predicates drives me nuts for the same reason |
| 14:46 | VFe | antares_: this changes everything |
| 14:47 | gfredericks | technomancy: it's a required thing? |
| 14:47 | technomancy | gfredericks: no, a cultural thing |
| 14:47 | Raynes | antares_: I'll hold you to it. |
| 14:47 | technomancy | gfredericks: well, it might be required in CL; not sure if the standard allows for ? |
| 14:47 | tcrayford | I really wish haskell allowed ? as part of a variable name :/ |
| 14:47 | Raynes | 'variable' |
| 14:48 | technomancy | I bet all widely-used implementations do, and elisp certainly does |
| 14:48 | Raynes | EVIL ONE |
| 14:48 | antares_ | Raynes: I know you are serious business |
| 14:48 | gfredericks | technomancy: oh right question marks |
| 14:48 | tcrayford | Raynes: im troll |
| 14:48 | Apage43 | it's pretty hairy though |
| 14:48 | Raynes | Apage43: You can have my $10 as well. |
| 14:48 | Raynes | It's bounty. |
| 14:48 | Raynes | I'll even tack on $1 for pain and suffering for having to use C. ;) |
| 14:49 | technomancy | hazard pay |
| 14:49 | antares_ | do C programmers get to retire earlier, too? |
| 14:49 | mynomoto | I'm still trying to use eval-in-project for a lein plugin. I got this code https://www.refheap.com/paste/13938 |
| 14:50 | SegFaultAX | Apage43: Y u no nif? |
| 14:50 | Apage43 | SegFaultAX: I've done NIFs too |
| 14:50 | mynomoto | And this error: Exception in thread "main" java.lang.ClassNotFoundException: squiggle.core, compiling:(NO_SOURCE_PATH:1:37) |
| 14:50 | Apage43 | I've built the VM for Android and iOS before and that required getting into the guts though |
| 14:50 | technomancy | mynomoto: it's best to use fully-qualified var names for referring to things not in core |
| 14:50 | SegFaultAX | Apage43: Then I /really/ feel your pain. |
| 14:50 | technomancy | at least for starters |
| 14:50 | Apage43 | also had to debug the VM on numerous occasions |
| 14:51 | SegFaultAX | Apage43: Eheh, Erlang on Android. Wut? |
| 14:51 | Apage43 | *and* iphone |
| 14:51 | Apage43 | it was for a product that packaged CouchDB |
| 14:51 | SegFaultAX | Apage43: But.. why? |
| 14:51 | SegFaultAX | Ah. |
| 14:51 | mynomoto | technomancy: my bad. Will do. |
| 14:51 | SegFaultAX | Still, pleasae no. |
| 14:52 | technomancy | mynomoto: but it sounds like the init form might be the culprit here |
| 14:52 | technomancy | confirm it's on the classpath, etc |
| 14:52 | cemerick | dnolen: any ideas re: a StackOverflow compiling a match form in one environment, not another (on the same commit in the same project)? |
| 14:52 | Apage43 | indeed, it was a silly idea, and we've luckily scrapped it in favor of just writing a CouchDB-compatible lightweight db for that stuff |
| 14:52 | Raynes | I'd do the port stuff myself, but goodness, I value my life more than that. |
| 14:52 | Apage43 | compatible meaning it syncs with it, not necessarily exposes the same API |
| 14:53 | dnolen | cemerick: hmm not really |
| 14:55 | SegFaultAX | Apage43: Why would you want such a thing to begin with? |
| 14:55 | mynomoto | technomancy: I'm running the plugin in that project folder. It should be in the classpath right? |
| 14:55 | cemerick | yeah, figured it'd be a longshot |
| 14:56 | Apage43 | SegFaultAX: sync. CouchDB replication is really nice for that. |
| 14:56 | technomancy | mynomoto: maybe print out (leiningen.core.classpath/get-classpath project) before calling eval-in-project so you can verify? |
| 14:56 | dnolen | cemerick: feel free to open a ticket w/ stack trace, it might be obvious or it might not. |
| 14:57 | dnolen | cemerick: does heroku AOT? |
| 14:57 | SegFaultAX | Apage43: But couch on a mobile device? Ugh. It doesn't seem like you have the CPU nor the memory to do anything more than the most trivial work. |
| 14:57 | Apage43 | that is: work offline for a bit, edit your local db, then connect up for a short time and sync it with some remote db. |
| 14:57 | cemerick | dnolen: good question, I don't recall....(goes to look) |
| 14:58 | Apage43 | SegFaultAX: that's why it was silly. The new thing is a much less silly, being a layer over SQLite that implements some of the couchdb functionality. |
| 14:58 | ppppaul | try-let sounds sexy |
| 14:58 | ppppaul | gist gist gist! |
| 14:59 | Raynes | refheap refheap refheap! |
| 14:59 | cemerick | dnolen: heh, yeah, it does :-P |
| 14:59 | SegFaultAX | Apage43: We built something like that at my last job (mobile games). But were actually storing transformations in the database which would be streamed to the server in blocks when they regained connectivity. |
| 14:59 | owengalenjones | anyone using :creds :gpg ever see an EOF error when trying to pull lein deps from an archiva repository? |
| 14:59 | SegFaultAX | Apage43: I'm curious, is your implementation open source? |
| 15:00 | amalloy | gfredericks: try-let sounds like toilet |
| 15:00 | gfredericks | amalloy: phew! |
| 15:00 | Apage43 | the new one isn't by me, but it's here https://github.com/couchbase/couchbase-lite-ios |
| 15:00 | gfredericks | amalloy: for several seconds I thought you were using "toilet" as a generic adjectivish thing to describe something you don't like |
| 15:00 | gfredericks | I can imagine tcrayford using the word that way |
| 15:00 | amalloy | haha |
| 15:01 | amalloy | that name is *pants*, sir |
| 15:01 | Apage43 | formerly called TouchDB |
| 15:01 | dnolen | cemerick: that's probably the issue |
| 15:01 | Apage43 | we had to slap branding on it |
| 15:01 | SegFaultAX | Apage43: Neat! Thanks. |
| 15:01 | dnolen | cemerick: there's a ticket for the AOT problem, would love some help on that one. |
| 15:02 | ppppaul | i used to couchdb |
| 15:02 | ppppaul | but not couchbase |
| 15:02 | ppppaul | they are a bit different |
| 15:03 | mynomoto | technomancy: It's in the classpath. |
| 15:06 | SegFaultAX | Is it just me or does github /feel/ very different when you're not logged in? |
| 15:07 | gideonite | hi i have a noob ring question: i can't seem to get form parameters from a request. |
| 15:07 | gideonite | when (:form-params req) i get a map with strange keys |
| 15:07 | gideonite | which are not symbols |
| 15:07 | gideonite | something like (user foobar) instead of (:user foobar) |
| 15:08 | gideonite | any advice? |
| 15:08 | SegFaultAX | gideonite: What middlewares are you using? |
| 15:08 | weavejester | gideonite: By default, parameters are strings |
| 15:08 | gideonite | should i being using wrap-params? |
| 15:08 | weavejester | Parameter keys, I mean, because a parameter name doesn't necessarily conform to what is allowed in a keyword |
| 15:09 | weavejester | For example, foo%20bar=baz translates to {"foo bar" "baz"} |
| 15:09 | SegFaultAX | gideonite: Are you using Compojure? |
| 15:09 | weavejester | The wrap-keyword-params middleware turns the parameter keys into keywords |
| 15:09 | gideonite | i'm actually using pedestal.io |
| 15:10 | SegFaultAX | Does pedestal use Compojure? |
| 15:10 | weavejester | But wrap-keyword-params only applies to (:params req) |
| 15:10 | weavejester | Pedestal doesn't use Compojure |
| 15:10 | SegFaultAX | Bummer. |
| 15:10 | weavejester | (:form-params req) will always have strings for keys |
| 15:10 | SegFaultAX | gideonite: https://github.com/weavejester/compojure/blob/master/src/compojure/handler.clj <- good example of some reasonable default middlewares. |
| 15:11 | weavejester | Presumably gideonite wants to do a lot of async work, which pedestal is designed for |
| 15:11 | gideonite | weavejester: right, but it does use ring. right now i'm just trying to set up something simple. ah, so i need to figure out how to get from a map where keys are string |
| 15:11 | gideonite | weavejester: eventually, yes. |
| 15:11 | weavejester | gideonite: Try accessing (:params req) |
| 15:12 | SegFaultAX | Is it safe to assume that pedestal sets up the common middlewares for you by default? |
| 15:13 | gideonite | weavejester: that does work. i now see that my question is really how to get from a map with strings as keys. that's already helpful |
| 15:13 | weavejester | gideonite: It's the same as getting from a map with keywords |
| 15:13 | weavejester | gideonite: Well, except that you can't use strings as functions |
| 15:13 | SegFaultAX | gideonite: Maps are functions of their keys. |
| 15:14 | weavejester | gideonite: So (params "foo") or (get params "foo") |
| 15:14 | SegFaultAX | gideonite: Keywords are functions, too. They try and get themselves from their argument. |
| 15:14 | gfredericks | dangit try-let is hard to write |
| 15:15 | gideonite | boom -- obviously it's get. noob questions! thanks so much |
| 15:15 | SegFaultAX | gideonite: Or using the map itself in function position, ##({"foo" 1 "bar" 2} "foo") |
| 15:15 | lazybot | ⇒ 1 |
| 15:15 | gideonite | there's also a function keyword fyi, if you're committed to having keywords |
| 15:17 | gideonite | SegFaultAX: haha, that seems complicated |
| 15:18 | SegFaultAX | gideonite: Why? |
| 15:18 | SegFaultAX | gideonite: As I said, maps are functions of their keys. That turns out to be really useful. |
| 15:19 | jcromartie | I am OK with putting important runtime state in a var. |
| 15:19 | jcromartie | there. I said it |
| 15:19 | gfredericks | "keys are functions of their maps" would be a fun terrible feature for a language |
| 15:19 | gfredericks | jcromartie: with alter-var-root? or with an atom? |
| 15:20 | jcromartie | not quite |
| 15:20 | jcromartie | I mean refs in vars |
| 15:20 | jcromartie | etc. |
| 15:20 | gfredericks | refs in vars in atoms in agents in actors in scala |
| 15:20 | jcromartie | yes |
| 15:20 | SegFaultAX | gfredericks: That's concurrency done right. |
| 15:20 | TimMc | gfredericks: I look forward (with some trepidation) to ##(format "lib-%04d" (rand-int 1e4)) |
| 15:20 | lazybot | ⇒ "lib-3236" |
| 15:20 | TimMc | (regarding keys and maps) |
| 15:21 | jcromartie | I think that a core namespace is the right place to bolt down some important things in place and put all the important parts together. |
| 15:21 | gfredericks | TimMc: mutable numbers first |
| 15:22 | gfredericks | TimMc: I resisted that naming pattern recently |
| 15:25 | [tab][tab][tab] | Oh my god this is the best nick. |
| 15:25 | SegFaultAX | [tab][tab][tab]: Hah |
| 15:26 | TimMc | ...and registered. |
| 15:27 | gideonite | SegFaultAX: sorry, you are absolutely right. that's the best thing to do. i guess strings don't evaluate to themselves? |
| 15:27 | gfredericks | they do |
| 15:27 | gfredericks | (eval "foo") => "foo" |
| 15:28 | SegFaultAX | gideonite: Strings always evaluate to themselves. |
| 15:29 | TimMc | Strings, keywords, vectors, maps, sets... |
| 15:29 | amalloy | they just aren't functions |
| 15:29 | gideonite | then why can't i go ("foo" {"foo" "bar"}) |
| 15:29 | SegFaultAX | gideonite: But they aren't functions. Keywords are and all they do is `get` themselves from their argument. |
| 15:29 | amalloy | TimMc: minus vectors, maps, and sets... |
| 15:29 | TimMc | amalloy: Eh? |
| 15:29 | gideonite | SegFaultAX: got it |
| 15:29 | amalloy | the vector [x] clearly does not evaluate to [x] |
| 15:29 | gfredericks | being evaluated and being called are different |
| 15:30 | gtrak | &(eval 'x) |
| 15:30 | lazybot | java.lang.SecurityException: You tripped the alarm! eval is bad! |
| 15:30 | TimMc | amalloy: Hmm... fair. |
| 15:30 | gtrak | CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:1) |
| 15:30 | SegFaultAX | gideonite: I think most people like to use keywords as functions if the maps their dealing with have keyword keys. |
| 15:31 | SegFaultAX | gideonite: Eg (:foo {...}) vs. ({...} :foo) |
| 15:31 | SegFaultAX | Despite them being equivalent |
| 15:31 | gtrak | the first will never give an NPE |
| 15:31 | SegFaultAX | gideonite: For all other types of keys, you pretty much have to use the map in function position. |
| 15:31 | amalloy | meh, i rarely use maps in function position. i usually just use get |
| 15:31 | TimMc | ,('foo {'foo 4}) |
| 15:31 | clojurebot | 4 |
| 15:31 | TimMc | ^ almost never used |
| 15:32 | SegFaultAX | TimMc: Literally never used. |
| 15:32 | clojurebot | TimMc: There is a Clojure patch on CLJ-1168 that seems like it should allow Leiningen to work with 1.5.0 and :jvm-opts ["-Dclojure.read.eval=unknown"] http://dev.clojure.org/jira/browse/CLJ-1168 |
| 15:32 | TimMc | Thanks, bot. Thanks... for nothing. |
| 15:32 | nz | what is difference between with-redefs and binding? other than binding works only with vars that are marked ^:dynamic? |
| 15:32 | SegFaultAX | TimMc: But it is interesting that keywords are effectively just symbols. |
| 15:32 | nz | ,(doc binding) |
| 15:32 | clojurebot | "([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values." |
| 15:32 | nz | ,(doc with-redefs) |
| 15:32 | callen | sometimes I think the bot was coded to be unreliable/weird on purpose. |
| 15:32 | clojurebot | "([bindings & body]); binding => var-symbol temp-value-expr Temporarily redefines Vars while executing the body. The temp-value-exprs will be evaluated and each resulting value will replace in parallel the root value of its Var. After the body is executed, the root values of all the Vars will be set back to their old values. These temporary changes will be visible in all threads. Useful for mockin... |
| 15:33 | TimMc | nz: The difference is that with-redefs is not thread-safe, alters the root, and should only be found in your test/ directory. |
| 15:33 | gfredericks | woah java is getting "default methods" for interfaces |
| 15:34 | TimMc | oh what |
| 15:34 | SegFaultAX | gfredericks: Oh? How does that make them different from abstracts? |
| 15:34 | gfredericks | they're on the interfaces instead of superclasses |
| 15:34 | nz | gfredericks: yep, it is so that List etc interfaces can work nicely with lambdas |
| 15:35 | SegFaultAX | Soo, Java is getting mixins via default interface methods? |
| 15:35 | gideonite | SegFaultAX: so in some sense :a evaluates to #(get % :a). i agree, it's a very nice concept |
| 15:35 | gfredericks | I am sitting 15 feet in front of Brian Goetz describing this |
| 15:35 | nz | you can add default implementation to interface. that impl is used if the implementing class doesn't implement the metod |
| 15:36 | TimMc | The slow slide into multiple inheritance. |
| 15:36 | SegFaultAX | TimMc: That's what I was thinking. |
| 15:36 | gfredericks | he said "java has always had multiple inheritance for types" and I'm not sure what that meant |
| 15:36 | SegFaultAX | TimMc: Very Ruby-esque. |
| 15:36 | gfredericks | is that what interfaces are? |
| 15:36 | nz | http://www.lambdafaq.org/do-default-methods-introduce-multiple-inheritance-to-java/ |
| 15:37 | SegFaultAX | gfredericks: Maybe that classes can implement an infinite number of interfaces? |
| 15:37 | tieTYT2 | can someone help me with this question? http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class |
| 15:38 | SegFaultAX | nz: Yup |
| 15:38 | tieTYT2 | I think i'm asking a fundamental clojure question here, not something specific to gen-class |
| 15:38 | nz | list.forEach(System.out::println) |
| 15:39 | SegFaultAX | nz: Although I never really would have called that multiple inheritance because it carries a slightly different connotation for me than simply implementing any number of interfaces. |
| 15:39 | nz | multiple inheritance of behavior |
| 15:40 | SegFaultAX | nz: That's what I usually associate with MI, the behavior part. But it's easy to adjust that mental model to include types. |
| 15:41 | SegFaultAX | Still, default methods means that Java can now properly implement the mixin pattern. I guess that's ok? |
| 15:44 | tieTYT2 | why does this return nil? (macroexpand-1 '(gen-class |
| 15:44 | tieTYT2 | :name com.sandbox.GeneratedClass |
| 15:44 | tieTYT2 | :methods [[hello [] String]])) |
| 15:44 | gfredericks | I think gen-class always expands to nil |
| 15:45 | nDuff | *nod*. |
| 15:45 | tieTYT2 | how's that possible? |
| 15:45 | gfredericks | it's a side-effecting macro |
| 15:45 | tieTYT2 | oh so I can't see what it's doing? |
| 15:45 | gfredericks | you can read the implementation |
| 15:45 | nDuff | tieTYT: It doesn't do anything at all except during ahead-of-time compilation. |
| 15:45 | gfredericks | the 7th rule of macro club is don't write side-effecting macros |
| 15:45 | tieTYT2 | oh right |
| 15:45 | tieTYT2 | ok well I really am stuck with this then |
| 15:46 | tieTYT2 | http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class |
| 15:46 | amalloy | tieTYT2: that is not a thing it is possible to do |
| 15:46 | amalloy | nor would it be terribly useful if you could |
| 15:46 | gfredericks | and java's getting this streaming interface |
| 15:46 | tieTYT2 | amalloy: ok thanks, at least now I know that. |
| 15:47 | SegFaultAX | Wow, gen-class is exceedingly complicated. |
| 15:47 | jcromartie | oh snap |
| 15:47 | jcromartie | cyclical dependency |
| 15:47 | tieTYT2 | amalloy: the reason I want to do that is because I want to make a function you use like this: (GET "url" [url] some-body) that will generate a jersey class |
| 15:47 | tieTYT2 | but I want each of those function calls to add a method to the gen-class |
| 15:48 | tieTYT2 | and I can't figure out how to do that a method at a time |
| 15:48 | TimMc | jcromartie: Having everything in core? |
| 15:49 | TimMc | *too much |
| 15:49 | jcromartie | had something important in a web.core, that was used by web.core.routes.foo |
| 15:49 | jcromartie | and vice versa |
| 15:53 | gfredericks | I think java just invented reducers? |
| 15:53 | jcromartie | foo.bar.baz should not use vars in foo.bar, as a general principal |
| 15:55 | beaky | are there progrmaming languages that are better than clojure? |
| 15:55 | ppppaul | no |
| 15:56 | ppppaul | clojure is best |
| 15:56 | SegFaultAX | beaky: Better than Clojure /for what/? |
| 15:56 | ppppaul | even for micro computing |
| 15:56 | AimHere | beaky > INTERCAL is better than clojure. |
| 15:56 | ppppaul | or, micro-codeing |
| 15:56 | beaky | ah |
| 15:56 | gfredericks | yes: it has been proven that either J or Dart is better than Clojure, but also that it is impossible to determine which one |
| 15:56 | gfredericks | this has been called the "J-Dart Indeterminacy Problem" |
| 15:56 | ppppaul | J <3 |
| 15:57 | ivan | if clojure doesn't do what you want, just write a sufficiently smart clojurescript emitter |
| 15:57 | beaky | hmm I should look into J |
| 15:57 | SegFaultAX | ppppaul: Have you seen Conway's GoL in APL? |
| 15:57 | ppppaul | i have |
| 15:57 | ppppaul | i was impressed |
| 15:58 | callen | beaky: fortran is way better than clojure |
| 15:58 | SegFaultAX | Such an excellent video: http://www.youtube.com/watch?v=a9xAKttWgP4 |
| 15:58 | beaky | but fortran isn't as general-purpose as clojure afaik |
| 15:58 | Chousuke | with a sufficiently smart compiler, (can-have? 'pony) returns true and a pony will be delivered shortly |
| 15:59 | beaky | it's just a dinosaur language for dinosaur numerical computing libs that have over 6 decades of optimization |
| 15:59 | amalloy | Chousuke: i would expect more like a piece of paper with the word pony to arrive |
| 15:59 | amalloy | (can-have? pony) might give you an actual pony |
| 15:59 | Chousuke | that may be |
| 15:59 | Chousuke | or maybe the compiler is feeling generous and gives you a pony sticker instead |
| 15:59 | ppppaul | i want pony |
| 16:00 | AimHere | I think if something has 60 years of optimization, then it's going to be pretty damn optimized, and quite likely to be the best at what it does. Therefore Fortran is Best Language |
| 16:00 | AimHere | QED |
| 16:00 | patchwork | I do all my computations on abacus |
| 16:00 | ppppaul | abacus is best language |
| 16:00 | gfredericks | the first language to be invented is necessarily the best |
| 16:00 | callen | AimHere: Fortran used to have a performance advantage on C due to design that has since been overcome with vectorization and compiler flags. |
| 16:01 | callen | AimHere: advantages that weren't entirely due to "time", keeping in mind that C has had quite a lot of industry dollars dumped into it. |
| 16:01 | SegFaultAX | AimHere: Also, quite a lot of math library code is still written in Fortran even today. |
| 16:01 | beaky | ah |
| 16:02 | TimMc | English is a pretty nifty programming language. Very expressive. However, a sufficiently powerful runtime can be quite expensive. |
| 16:02 | callen | TimMc: I hear grad students make good interpreters. |
| 16:03 | callen | beaky: is somebody commissioning you to ask questions for a dictionary with definitions composed entirely of IRC logs? |
| 16:03 | AimHere | English is just Cobol++ |
| 16:03 | Apage43 | English interpreters tend to be pretty slow, comparatively. |
| 16:04 | Apage43 | You can sometimes get one to translate your English to something more computer usable though :) |
| 16:06 | TimMc | English is very prone to non-deterministic bugs. For instance, if you issue the same command multiple times, it is likely to stop working. |
| 16:06 | guns | Does lazy-seq guarantee safe concurrent access to the next value? |
| 16:06 | beaky | I guess all programming languages have a raison d'etre; hence there is no best one |
| 16:06 | TimMc | The result is that the more you test a program, the less likely it is to work! |
| 16:06 | guns | I found what I thought was an unsynchronized mutation in a deftype on (next) |
| 16:07 | Chousuke | english is not a very good programming language |
| 16:07 | guns | but the object was wrapped in a lazy-seq and survived hammering from 1000 threads! |
| 16:07 | Chousuke | compilation takes months or years, might not terminate, and the end result might or might not correspond to what you mean |
| 16:07 | guns | sorry for interleaving the conversation. |
| 16:08 | TimMc | guns: You're not the one who should be apologizing. :-P |
| 16:08 | TimMc | Is the code somewhere where we can see it? |
| 16:08 | guns | TimMc: If you're interested, I could gist it |
| 16:09 | Raynes | &(interleave '[Chousuke TimMc] '[guns Raynes]) |
| 16:09 | lazybot | ⇒ (Chousuke guns TimMc Raynes) |
| 16:09 | Raynes | Sorry for interleaving guys! |
| 16:10 | Chousuke | You made me gun TimMc, Raynes |
| 16:10 | Chousuke | that is not nice |
| 16:10 | Raynes | Nice. |
| 16:12 | tbaldridge | guns: yes it does: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java |
| 16:12 | tbaldridge | notice how sval and seq anre synchronized, thus only one thread can be running those methods on the same object at a time. |
| 16:12 | guns | tbaldridge: I took a look at that file, but didn't immediately see an answer to my inquiry |
| 16:13 | guns | I guess I should have read closer |
| 16:13 | tbaldridge | guns: yeah it's a nasty bit of code. |
| 16:13 | guns | tbaldridge: Ah, I see it now. Brilliant |
| 16:14 | tbaldridge | that's actually the cool thing about Seqs as opposed to interators or .NET's IEnumerable. running over the same seq 100 times will only actually calculate the seq once. |
| 16:15 | guns | I was using a Random and BitSet in my deftype; I thought I would have to lock and clone, but lazy-seq took care of all the details |
| 16:16 | tieTYT2 | amalloy: i don't understand why you're saying that would not be very useful |
| 16:19 | tieTYT2 | I'm getting the sense clojure is a bad language to build a java-code generator |
| 16:19 | Apage43 | i once used clojure to generate C. I wish I could stop remembering. |
| 16:20 | Raynes | s/clojure/any language/ |
| 16:24 | tieTYT2 | I'm trying to write a clojure DSL to generate Jersey code, but it doesn't seem possible to me since gen-class won't let you pass in a dynamic list of method names |
| 16:26 | TimMc | Macros to the "rescue"... |
| 16:26 | tieTYT2 | a macro that generates a gen-class ? |
| 16:27 | tieTYT2 | I didn't know that was an option |
| 16:27 | raek | *sigh* why is the syntax highlighting suddenly gone for me in clojure-mode... |
| 16:29 | Raynes | raek: Holy shit. I haven't seen you speak in like a year. |
| 16:29 | Raynes | How are you? Besides your emacs being broken? |
| 16:33 | andrew__ | this might be a ridiculous question, but what is the difference in terms of java interop between using . and /? for example, I sometimes see ServerSocketChannel/open but on the next line I'll see (InetSocketAddress. "localhost" 5000) |
| 16:33 | raek | Raynes: things are good... |
| 16:34 | andrew__ | are only certain things able to use the / for interop, whereas others must use the . ? |
| 16:34 | raek | have been playing with Haskell for some time (and I also have a job nowadays) |
| 16:35 | dnolen | andrew__: / for static methods |
| 16:35 | raek | andrew__: (Foo/bar) means bar method of Foo class, but (Foo.) means Foo constructor |
| 16:35 | andrew__ | much appreciated dnolen and raek |
| 16:41 | iamdrw | greetings. is there a profiler for clojure? because profiling via time makes me go mad |
| 16:42 | tcrayford | iamdrw: all the jvm profilers work |
| 16:42 | tcrayford | so jvisualvm works (and you prolly already have it installed), yourkit is free if you're open source and mention it on your page, and much better than jvisualvm |
| 16:43 | nightfly__ | profiling results might be dissapointingly vague if using higher-order functions though |
| 16:43 | amalloy | technomancy: how do i force refetching of snapshot dependencies? |
| 16:44 | technomancy | amalloy: lein -U deps |
| 16:44 | TimMc | iamdrw: If you just want benchmarking of different algorithms, criterium is excellent. |
| 16:44 | amalloy | thanks |
| 16:45 | iamdrw | criterium seems what I was looking for. Thanx |
| 16:47 | amalloy | criterium is great if you want to know how long a particular thing takes; yourkit is more work, but is better if you want to know what is taking so long |
| 16:47 | tcrayford | they do different jobs for you ;) |
| 16:49 | weavejester | Hmmm… there might be a bug in core.memoize… either that or I'm misreading this stacktrace |
| 16:49 | amalloy | weavejester: core.memoize and core.cache both do a big pile of reflection for no particular reason. i'd consider that a bug, in libraries designed to improve performance |
| 16:51 | weavejester | I get this interesting stacktrace, which looks like a race condition: https://gist.github.com/weavejester/60a0a0bf334af85ffdfe |
| 16:53 | amalloy | ,@nil |
| 16:53 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 16:53 | amalloy | funny that it thinks that's a Future, but whatever |
| 16:54 | weavejester | I think that's the last type of deref it tries... |
| 16:54 | hiredman | because deref now works on non-clojure created java futures |
| 16:54 | hiredman | yet another hand rolled protocol |
| 16:55 | cemerick | dnolen_: yeah, it was AOT. I'll see if I can track it down. Hopefully I can be 1/3 with core.match issues. :-P |
| 16:55 | dnolen_ | cemerick: :) |
| 16:57 | weavejester | It would seem to imply that (swap! cache through* f args) is returning nil for some reason |
| 16:58 | weavejester | Which implies clojure.core.cache/through is... |
| 16:58 | weavejester | I'm not seeing how that's possible, however... |
| 16:59 | dnolen_ | iamdrw: I recommend YourKit, criterium appears nice for only high level benchmarking |
| 16:59 | dnolen_ | er profiling |
| 16:59 | amalloy | weavejester: of course it's possible: cache is a protocol, and you can implement it so that every function returns nil |
| 17:00 | weavejester | amalloy: Yeah, but all the functions in the TTLCache seem to return not-nil |
| 17:03 | mikerod | When someone was learning Clojure the other day, they posted the question "so what's the "right" thing to do other than the giant, procedural let block?" I didn't have a good answer or a good reference. However, I feel there is much more to programming in Clojure than a "big procedural let block." Hmm. |
| 17:04 | mikerod | I've been puzzling over what to say to this. |
| 17:04 | bbloom | depends on the problem at hand |
| 17:04 | bbloom | but generally the answer is more functions.... |
| 17:05 | mikerod | Yeah, I think it was a question directed at what does the functional paradigm offer over the "big procedural let block" perhaps. |
| 17:05 | mikerod | More functions is appropriate I'd say. :P |
| 17:05 | bbloom | it's very common to see a (-> pipeline of step functions like this) where you thread a {:map "of" :keys "like" :this "through"} |
| 17:05 | technomancy | what does being in a let block have to do with being procedural? |
| 17:06 | bbloom | technomancy: i assume he means that he is shadowing names for each incremental "change" |
| 17:06 | mikerod | I don't think of them as coupled. |
| 17:06 | technomancy | bbloom: hm; that's a strange use of the word procedural |
| 17:07 | bbloom | technomancy: i agree, but i've seen quite a few people new to functional programming use single static assignment in a way that feels like a throwback to some C code |
| 17:07 | mikerod | I agree it was an open ended question and over generalized. I think bbloom had the right description with "shadowing names for each incremental change". |
| 17:07 | technomancy | I don't think there's anything wrong with shadowing names for each change if it's a case where -> is not suitable for argument order reasons |
| 17:08 | technomancy | that pattern alone does not make code procedural |
| 17:08 | bbloom | i agree with technomancy, but i'll add that after a small handful of let bindings & your function gets too big, it is a code smell |
| 17:09 | technomancy | right; but function size is orthogonal to let-rebinding |
| 17:09 | technomancy | well, they may be correlated, I guess |
| 17:09 | pjstadig | correlation is orthogonal! |
| 17:09 | bbloom | technomancy: forgive me for jumping to conclusions, but mikerod seems to have suggested that i read his & his colleagues' minds... :-) |
| 17:10 | mikerod | So more functions obviously gives you more abstraction, modularity, reuse, comprehensibility, etc. |
| 17:10 | bbloom | mikerod: it's also just easier to work with if you stick some stuff in a map b/c you can print it out |
| 17:10 | mikerod | bbloom: I don't agree with the question I posted, I just have had a hard time formulating an appropriate response. |
| 17:11 | bbloom | mikerod: yeah, it's hard to teach someone a new way of thinking |
| 17:11 | mikerod | bbloom: Indeed. I appreciate your feedback on it too. |
| 17:14 | Raynes | guns: Oh, you're the vim-clojure-static guy. |
| 17:14 | Raynes | guns: I commend you on your efforts good sir. |
| 17:17 | seancorfield | just saw the discussion about clj-time... i inherited it and am not particularly attached to the names in it... that said, introducing 'second' would cause many users of clj-time to see the ugly "warning ... name already bound to ..." message on :use or :refer :all ... which is how most code uses it i suspect |
| 17:17 | gfredericks | seancorfield: I think most of our usages of clj-time are :as or :refer [...] |
| 17:18 | seancorfield | but it wouldn't be the only library that shadows a core function and folks know how to get around it... |
| 17:18 | gfredericks | mostly on principle of avoiding :use/:all |
| 17:18 | seancorfield | gfredericks: you could well be right |
| 17:18 | seancorfield | and the docs could make it clear too |
| 17:18 | gfredericks | seancorfield: just piping up with a data point |
| 17:18 | seancorfield | clojure.java.jdbc has shadowed resultset-seq for a long time, for example |
| 17:19 | TimMc | seancorfield: Maybe that's a good reason to call it "second" -- fewer people using :use. |
| 17:19 | seancorfield | (but core/resultset-seq is a silly place for that function!) |
| 17:19 | seancorfield | TimMc: heh, yeah, strong encouragement to change their ways :) |
| 17:20 | seancorfield | feel free to create an issue https://github.com/clj-time/clj-time/issues (when github comes back up :) |
| 17:21 | Raynes | seancorfield: If that's how most code uses it then that code is wrong and needs to be changed anyways. |
| 17:27 | seancorfield | "most code is wrong" -- Raynes, April 2013 :) |
| 17:27 | seancorfield | i agree, btw |
| 17:28 | Raynes | seancorfield: I'm writing an issue. |
| 17:29 | Raynes | https://github.com/clj-time/clj-time/issues/70 |
| 17:32 | seancorfield | thank you sir! |
| 17:41 | Raynes | seancorfield: https://twitter.com/mikeflynn_/status/327175064644628481 |
| 17:43 | patchwork | Is *worst* a dynamic var there? |
| 17:45 | patchwork | Anyone use morph for modeling global state? https://github.com/blancas/morph/wiki/Modeling-Global-Data |
| 17:45 | patchwork | I am looking at it as an alternative to having a dynamic var for configuration |
| 17:45 | patchwork | might be more trouble than it's worth |
| 17:46 | patchwork | I like the idea of having pure functions access global values without passing config vars everywhere though |
| 17:47 | TimMc | Raynes: I wonder how much of that is just "time is hard" and the guy thinks it is clj-time's fault. |
| 17:47 | Raynes | TimMc: All of it I'd wager. |
| 17:51 | seancorfield | i replied on twitter suggesting he open issues with improvement ideas |
| 17:51 | seancorfield | a lot of ppl are quick to criticize but slow to actually suggest concrete improvements |
| 17:52 | joegallo | well, it's easy to take potshots from the peanut gallery, much harder to climb down and start working ;) |
| 17:54 | TimMc | You can't really file a proper (design) bug report in 140 characters, but if you file a github issue you don't get to be ranty in front of your friends, and we can't have *that*. |
| 17:58 | rasmusto | why does this behave differently at the repl and when doing 'lein run'?: (map (comp #(.exists %) as-file) ["." "target" "/tmp" "fjoewifj"]) ; (I only get false when doing lein run) |
| 17:58 | callen | Raynes: I +1'd your issue. |
| 17:59 | callen | Raynes: WITH RUV |
| 17:59 | Raynes | callen: Good on ye, sir. |
| 18:01 | seancorfield | callen: changing everything to plurals would be kinda disruptive to existing users... and i think there are already some singular and plural versions of the same thing? |
| 18:01 | seancorfield | i'll have to go dig into the API when i get to that |
| 18:02 | Raynes | tpope: It'd be cool if I could pass a commit message to :Gcommit somehow. |
| 18:03 | callen | seancorfield: I'm open to superior alternatives that don't rest on "don't fix things" |
| 18:03 | Raynes | tpope: It'd be useful for quick commits with short messages. |
| 18:03 | callen | seancorfield: you could have a migration period where using the old names pukes a warning and lets them know the next semver compliant version will get rid of the old names. |
| 18:04 | SegFaultAX | Raynes: But if you're already in the editor, what does that actually buy you? |
| 18:05 | Raynes | SegFaultAX: About 4 keystrokes. |
| 18:05 | rasmusto | hey Raynes, can I bounce a fugitive+fireplace idea/pull req off of you? |
| 18:05 | SegFaultAX | i:wq is too much? |
| 18:05 | Raynes | SegFaultAX: Yes. |
| 18:05 | SegFaultAX | I guess i<esc>:wq |
| 18:05 | Raynes | rasmusto: Sure, but I have nothing to do with either of those projects. |
| 18:05 | rasmusto | I'm wondering if I should submit a pull request for this: https://github.com/rasmusto/vim-fireplace/commit/f8ae7c429aaa4a6375dbbade239b5f1b82538506 |
| 18:06 | rasmusto | Raynes: I'm just curious if anyone would use it |
| 18:06 | Raynes | I don't think I use fugitive nearly well enough for this to be useful to me in particular, but that doesn't mean it isn't good. |
| 18:07 | rasmusto | It lets you use cpp when inside of a :Gdiff window, so you can throw old code at the REPL |
| 18:07 | Raynes | That sounds totally useful. |
| 18:07 | Raynes | You should run it by tpope. |
| 18:07 | rasmusto | I've pinged him a few times, which is why I was wondering about just making an issue/preq |
| 18:07 | Raynes | Yeah, that's best. He isn't around particularly often. |
| 18:08 | rasmusto | kk |
| 18:19 | rocco` | can someone help me with something |
| 18:19 | TimMc | rocco`: Just go ahead and ask your question; if someone can help they will answer. |
| 18:20 | rocco` | I'm running a repl in emacs and I'd like for a function running in a different thread to print into the repl |
| 18:21 | rocco` | right now I have no idea where it prints because I don't understand the *in* and *out* streams |
| 18:23 | TimMc | Oh, that can be tricky. I remember something about nREPL binding a new *out* for each new entry, too. |
| 18:24 | rocco` | what would be the preferred way to do it? |
| 18:27 | technomancy | use bound-fn for your thread maybe |
| 18:29 | TimMc | rocco`: Oh right, how are you starting that thread? |
| 18:30 | rocco` | using the java Thread start |
| 18:30 | rocco` | should I use clojure abstractions instead? |
| 18:31 | rocco` | I'm just learning this |
| 18:31 | rocco` | I'm trying to run a socket server with server-socket from the old contrib |
| 18:31 | rocco` | and I want it to speak to me :) |
| 18:37 | whinub | Hey guys, I'm pretty new to clojure but I was wondering if anyone could recommend a decent sized program / project with good documentation that I could read through and learn from. |
| 18:38 | rocco` | whinub: how about the clojure implementation itself? |
| 18:40 | TimMc | The Clojure implementation breaks all the Clojure dev rules. :-/ |
| 18:40 | technomancy | that's not a very good way to learn |
| 18:40 | TimMc | Leiningen is pretty nice. |
| 18:40 | technomancy | TimMc: as long as you skip the profile merge stuff =) |
| 18:41 | beppu | rocco`: this one is relatively small and is well documented. https://github.com/Engelberg/instaparse |
| 18:42 | beppu | (that last one was for whinhub) |
| 18:42 | rocco` | :) |
| 18:43 | whinub | Thanks for the suggestions guys, will definitely be checking them out. |
| 18:43 | rocco` | I'm also going to check it out |
| 18:44 | TimMc | rocco`: clojure.core/future and other multi-threaded constructs generally convey bindings such as *out* to the new thread. |
| 18:46 | rocco` | makes sense |
| 18:46 | rocco` | will try |
| 18:55 | rocco` | there's something about lein I don't understand |
| 18:56 | rocco` | is running a lein repl the same as doing a jack-in |
| 18:56 | callen | whinub: web app? |
| 18:56 | rocco` | no just ordinary app |
| 18:56 | callen | rocco`: I wasn't talking to you. |
| 18:57 | callen | whinub: do you want to see what a clojure web app looks like? |
| 19:01 | technomancy | rocco`: jack-in is just `lein repl :headless` plus connecting an elisp client to it |
| 19:02 | SegFaultAX | whinub: If so, refheap and 4clojure are both open source. |
| 19:02 | technomancy | as is clojars |
| 19:03 | tpope | Raynes: :Gcommit -m works |
| 19:04 | Raynes | tpope: Of course it does. Because you're tpope. I should have just known. |
| 19:23 | bingo | Any one has experience installing with brew install leiningen 2.1.3 in mac osx? |
| 19:23 | Raynes | Meh, don't bother. |
| 19:23 | amalloy | don't use brew |
| 19:23 | Raynes | Just install via the shell script. |
| 19:23 | technomancy | homebrew is kind of silly |
| 19:23 | Raynes | Don't use a package manager for anything related to Clojure ever. |
| 19:23 | bingo | oh i see. |
| 19:23 | Raynes | technomancy: It's perfectly fine for other things, but it's silly for this and Clojure in general. |
| 19:23 | technomancy | Raynes: I disagree |
| 19:24 | Raynes | amalloy: OS X comes with a JVM iirc. |
| 19:24 | Raynes | technomancy: What package manager would you propose I use? |
| 19:24 | Raynes | None at all? |
| 19:24 | whinub | callen: Hey sorry about delay went to cook some dinner. Taking a look at a web app would be awesome. What do you recommend? |
| 19:24 | Raynes | I kind of need one. |
| 19:24 | technomancy | Raynes: apt-get or nix |
| 19:24 | amalloy | technomancy: brew is silly, but it's better than the alternatives on osx |
| 19:24 | Raynes | And this is the least shitty of all of them. |
| 19:24 | technomancy | I don't know of any other good ones |
| 19:24 | Raynes | technomancy: I need one that's actually useful. |
| 19:24 | technomancy | amalloy: I don't dispute that |
| 19:25 | Raynes | Nix is great and all, but I have things to do besides making packages for everything I ever use. |
| 19:25 | bbloom | brew has been 1) fast 2) (generally) up-to-date and 3) not-horribly-broken... which is not something that can be said for any other OSX package manager |
| 19:25 | Raynes | My only problem with brew is that at least 70% of the packages I've ever tried to install would break while installing in one way or another. |
| 19:25 | Raynes | Fortunately they fix these problems relatively fast. |
| 19:26 | bingo | Well any way, I have been struggle of trying to run lein but it is complaining of depencies. I was running lein deps, and i still havin ghte same issue. |
| 19:26 | Raynes | (70% is an exaggeration) |
| 19:26 | bbloom | Raynes: clearly. |
| 19:26 | technomancy | stockholm syndrome much? |
| 19:26 | bbloom | meanwhile, plan 9 namespaces would dramatically simplify every package manager ever. |
| 19:27 | pjstadig | my only problem with driving on the road is that 70% if the time i die on the way to my destination |
| 19:27 | technomancy | pjstadig: other than that, the weinermobile is a great form of transportation |
| 19:28 | Raynes | But fortunately the paramedics resuscitate you relatively fast? |
| 19:28 | technomancy | it's aerodynamic and stuff |
| 19:28 | Raynes | Not sure if that metaphor goes all the way here. |
| 19:29 | pjstadig | (it was an exaggeration) |
| 19:29 | Raynes | Touché. |
| 19:31 | patchwork | 70% of all exaggerations result in developer death |
| 19:31 | bbloom | i myself has died literally thousands of times |
| 19:37 | weavejester | I think I've figured out why core.memoize/memo-ttl occassionally excepts |
| 19:37 | weavejester | Unfortunately I'll need to use JIRA to report it *sigh* |
| 19:40 | amalloy | weavejester: send fogus an email, and maybe he'll fix it for you in secret |
| 19:40 | rationalrevolt | ,(let [o '+] (o 1 2)) |
| 19:40 | clojurebot | 2 |
| 19:40 | weavejester | amalloy: I think I might raise it on clojure-dev first. I'd like a second opinion or two |
| 19:40 | rationalrevolt | am i not doing this right? |
| 19:40 | Bronsa | I still don't understand what's preventing contrib libraries from using github issues |
| 19:41 | amalloy | rationalrevolt: '+ is a symbol, not the addition function |
| 19:41 | amalloy | + is the addition function |
| 19:41 | patchwork | ,(let [o +] (o 1 2)) |
| 19:41 | clojurebot | 3 |
| 19:41 | weavejester | Do symbols act as functions to maps, the same as keywords? |
| 19:41 | amalloy | yesz |
| 19:42 | weavejester | ,('+ {'+ 2}) |
| 19:42 | clojurebot | 2 |
| 19:42 | weavejester | ,('+ {'+ 2} :not-found) |
| 19:42 | clojurebot | 2 |
| 19:42 | weavejester | ,('+ {'+ 3} :not-found) |
| 19:42 | clojurebot | 3 |
| 19:42 | weavejester | ,('+ 3 :not-found) |
| 19:42 | clojurebot | :not-found |
| 19:42 | weavejester | Just checking :) |
| 19:43 | weavejester | rationalrevolt: So yep, ('+ 1 2) is the same as (get 1 '+ 2) |
| 19:44 | weavejester | rationalrevolt: It tries to lookup a key '+ on 1, but since 1 isn't a map it fails and returns the failure result, which has been set to 2. |
| 19:44 | amalloy | i thought that was supposed to throw an exception in 1.5 now |
| 19:44 | amalloy | looking things up in a non-map |
| 19:44 | weavejester | ,*clojure-version* |
| 19:44 | clojurebot | {:major 1, :minor 5, :incremental 0, :qualifier "RC6"} |
| 19:44 | amalloy | ,(contains? 4 3) |
| 19:44 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: java.lang.Long> |
| 19:44 | amalloy | ,(get 4 3) |
| 19:44 | clojurebot | nil |
| 19:44 | amalloy | apparently it's just the contains? check, not get |
| 19:45 | Bronsa | amalloy: the get patch didn't get into 1.5 afaik |
| 19:47 | rationalrevolt | thanks weavejester |
| 20:01 | bingo | Hi Anyone, I would like to get someone who has experience install leiningen on mac osx 10.8.2 |
| 20:02 | amalloy | https://github.com/technomancy/leiningen/blob/master/README.md#installation |
| 20:02 | bingo | let me try again. |
| 20:16 | bttf | why can't i :use two different namespaces that have the same method defined ? |
| 20:16 | bttf | all calls to that method are explicity dereferenced to their respective namespace |
| 20:17 | amalloy | bttf: you want require, not use. use is explicitly for non-aliased names |
| 20:18 | bttf | amalloy: but can i require without aliasing ? |
| 20:19 | bttf | wait what is the aliasing part ... (require foo.bar as bar) or (require foo) so that i only have to type bar |
| 20:19 | bttf | (require foo.bar :as bar) |
| 20:20 | Bronsa | (require '[foo.bar :as bar]) |
| 20:20 | Bronsa | or (ns .. (:require [foo.bar :as bar])) |
| 20:20 | bttf | oh right |
| 20:22 | bttf | ok seems i was confused about require |
| 20:24 | mynomoto | technomancy: I did the fun project of find repetitions in code. But still no luck turning it into a lein plugin. And it was not that fun :) https://github.com/mynomoto/lein-repetition |
| 20:26 | mynomoto | If someone knows how to make this works as a lein plugin I'd be glad. Can't require the project namespace. |
| 20:26 | technomancy | huh, why do you need it to be a lein plugin |
| 20:26 | technomancy | ? |
| 20:28 | technomancy | err--why do you need to cross the boundary between leiningen and the project? |
| 20:28 | technomancy | can't you do it exclusively through static analysis? |
| 20:29 | mynomoto | technomancy: Doesn't need, just trying to learn something new. |
| 20:30 | technomancy | sure |
| 20:30 | mynomoto | It needs to know if a var is bounded in the ns or it will make it generic. |
| 20:30 | technomancy | oh, ok |
| 20:31 | technomancy | I guess you can't assume all vars are created by def or defn because of macroexpansion |
| 20:31 | technomancy | it looks like you're trying to require plugin namespaces from inside eval-in-project though; that's probably where it's breaking |
| 20:32 | technomancy | you can only require things from :dependencies |
| 20:32 | mynomoto | technomancy: But I can change the project dependencies right? |
| 20:33 | mynomoto | Or could put everything in one file... |
| 20:33 | technomancy | mynomoto: you could add to :dependencies but that can get hairy when profiles come into play |
| 20:34 | technomancy | if you can run everything inside the project process it's simpler |
| 20:34 | technomancy | just say "add this to :dependencies and then run lein run -m repetition.finder" or something |
| 20:34 | technomancy | or if the code to be run in the project isn't that big you could build it up as one big form like `lein test` does |
| 20:35 | technomancy | but that gets unmanageable once you have more than a page or so |
| 20:36 | mynomoto | Ok, I will try the lein run way. Thanks. |
| 21:01 | rocco`` | is there a way to access a thread if you deleted the reference to it |
| 21:01 | rocco`` | I mean a function that's running in that thread |