2014-01-26
| 00:02 | quizdr | the beauty of 4clojure is in learning that your function (fn [& a] (apply concat (map #(list % %2) (first a) (second a)))) can be rewritten simply as mapcat list, had you only known mapcat existed. |
| 00:06 | devn | this is also a little bit closer i guess... |
| 00:06 | devn | ,(map second (filter #(= 'clojure.core/declare (when (coll? %) (first %))) (macroexpand-1 '(defrecord fooBaz [x y z])))) |
| 00:06 | clojurebot | (->fooBaz map->fooBaz) |
| 00:06 | devn | ,(resolve 'fooBar) |
| 00:06 | clojurebot | nil |
| 00:09 | devn | err |
| 00:09 | devn | ,(defrecord fooBar []) |
| 00:09 | clojurebot | sandbox.fooBar |
| 00:09 | devn | ,(ns-resolve *ns* 'fooBar) |
| 00:09 | clojurebot | sandbox.fooBar |
| 00:12 | cark | ,(def test "hello") |
| 00:12 | clojurebot | #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)> |
| 00:12 | cark | hum |
| 00:12 | cark | clojurebot shouldn't let you define records i think |
| 00:13 | cark | ,(->fooBat) |
| 00:13 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ->fooBat in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 00:13 | cark | ,(->fooBar) |
| 00:13 | clojurebot | #sandbox.fooBar{} |
| 00:13 | devn | why not? |
| 00:14 | cark | you can polute the namespace, maybe dos it by defining many record types |
| 00:14 | devn | it does it in a sandbox |
| 00:14 | cark | right but the sandbox is still there isn't it |
| 00:14 | devn | for now |
| 00:15 | devn | i think it gets cleaned up regularly |
| 00:15 | cark | you could write a script to make it go out of memory, and maybe crash |
| 00:15 | cark | then why not let me def a var ? |
| 00:15 | cark | same problem |
| 00:16 | devn | ,(let [shadow 1] (+ shadow 1)) |
| 00:16 | clojurebot | 2 |
| 00:16 | devn | ,(let [shadow "shadow"] (str shadow " puppets")) |
| 00:16 | clojurebot | "shadow puppets" |
| 00:17 | devn | maybe he runs it in an env that makes that not matter |
| 00:18 | oracle_ | How to understand the: (map #(%1 %2) (cycle [inc identity]) [1 2 3 4 5 6 7 8 9 10])? |
| 00:18 | cark | he can't be "out of memory" proof |
| 00:18 | oracle_ | what's the meaning of "(cycle [inc identity])"? |
| 00:18 | cark | or i want his box |
| 00:19 | cark | oracle_: it's an infinite list : '( in identity inc identity ....) |
| 00:19 | devn | cark: im saying that maybe it (the vm/machine/whatever) just gets axed if it lives beyond its means |
| 00:19 | cark | oracle_: it's an infinite list : '(inc identity inc identity ....) |
| 00:19 | dissipate | clojurebridge is just for women? wtf |
| 00:19 | dissipate | that's ridiculous |
| 00:19 | devn | is it really? |
| 00:20 | dissipate | devn, as a man, why can't i get free workshops? :( |
| 00:20 | devn | idk, you can if you're in my town |
| 00:20 | devn | i dont know where you read that |
| 00:20 | dissipate | devn, which town? |
| 00:20 | devn | Madison, WI |
| 00:21 | devn | dissipate: my suggestion is to not read the "for women" part too seriously |
| 00:21 | oracle_ | but if I run " (take 10 (cycle [inc identity]))" it didn't return a list, instead it return "(#<core$inc clojure.core$inc@3e353f6a> ......" |
| 00:21 | devn | just show up |
| 00:22 | cark | oracle_: look a this : |
| 00:22 | devn | inc is a function |
| 00:22 | cark | ,(take 10 (cycle [1 2])) |
| 00:22 | clojurebot | (1 2 1 2 1 ...) |
| 00:22 | devn | identity is a function |
| 00:22 | devn | ,identity |
| 00:22 | clojurebot | #<core$identity clojure.core$identity@fbbe3f> |
| 00:22 | devn | ,inc |
| 00:22 | clojurebot | #<core$inc clojure.core$inc@1d1fda> |
| 00:22 | devn | ,(take 4 (cycle [inc identity])) |
| 00:22 | clojurebot | (#<core$inc clojure.core$inc@1d1fda> #<core$identity clojure.core$identity@fbbe3f> #<core$inc clojure.core$inc@1d1fda> #<core$identity clojure.core$identity@fbbe3f>) |
| 00:23 | devn | ,(take 4 (cycle ['inc 'identity])) |
| 00:23 | clojurebot | (inc identity inc identity) |
| 00:23 | devn | ,(take 4 (cycle '(inc identity)) |
| 00:23 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 00:24 | cark | it's pretty hard at first to see functions used as common data, stored in lists and whatnot |
| 00:24 | devn | ,(take 4 (cycle '(inc identity))) |
| 00:24 | clojurebot | (inc identity inc identity) |
| 00:24 | TEttinger | ztellman, those google ads were brilliant |
| 00:24 | jack_rabbit | ,(doall (range)) |
| 00:24 | clojurebot | #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space> |
| 00:24 | ztellman | TEttinger: ha, thanks |
| 00:24 | devn | jack_rabbit: dont break the bot :( |
| 00:24 | jack_rabbit | devn, He can survive it. :) |
| 00:24 | devn | (inc ztellman) |
| 00:24 | lazybot | ⇒ 8 |
| 00:24 | cark | it's the "kill clojurebot" night |
| 00:24 | TEttinger | (inc ztellman) |
| 00:24 | lazybot | ⇒ 9 |
| 00:24 | devn | cark: id like to see you try |
| 00:24 | quizdr | (inc clojurebot) |
| 00:24 | lazybot | ⇒ 33 |
| 00:25 | devn | ive run a couple millions sexps in a sandbox from this channel |
| 00:25 | devn | and had no issues |
| 00:25 | cark | devn : i don't want to write that script we talked about, but you may do it =P |
| 00:25 | devn | million* |
| 00:25 | TEttinger | also, ztellman have you considered a counterpart to primitive-math that provides primitive-coerced math ops? |
| 00:25 | devn | cark: my guess is you couldn't actually DDoS him with it |
| 00:25 | devn | err DoS |
| 00:25 | cark | devn : got to try it to be sure |
| 00:25 | devn | whichever worked i guess |
| 00:26 | ztellman | TEttinger: can you expand on that? I'm not sure what you mean |
| 00:27 | dsrx | got an http-kit question. if I run this namespace from lein run, and I connect and send messages the printlns inside the on-close and on-receive handlers print to the console. but if I load that namespace into a repl and (start) there, I do not see anything printed to the repl https://www.refheap.com/27692 |
| 00:27 | TEttinger | well to avoid the warnings primitive-math gave me (about 400 in one file I think), I changed all my non-float arithmetic to use some macros like +_ and *_ . those just coerce both args to long and add them |
| 00:27 | TEttinger | I don't know if there's a faster way |
| 00:28 | cark | dsrx: there is an annoying phenomenon with printing out of the main thread and nrepl |
| 00:28 | ztellman | TEttinger: coercion at the point of the arithmetic call isn't necessarily the right thing to do |
| 00:28 | ztellman | ideally you change something upstream, so it's not boxing at all |
| 00:28 | cark | dsrx: sometimes work and sometimes doesn't |
| 00:28 | devn | cark: im tempted |
| 00:28 | dsrx | cark: ah, I see |
| 00:28 | devn | im afraid of hiredman, but i feel like he probably took care of this scenario |
| 00:29 | TEttinger | I think I was using type hints incorrectly on my functions that returned numbers |
| 00:29 | devn | shall we try it? |
| 00:29 | dsrx | cark: well, I guess i can always swap messages into an atom and read them that way :P |
| 00:29 | devn | ,(doseq [x (repeatedly 100000 #((comp symbol str) (java.util.UUID/randomUUID)))] (eval `(defrecord ~x []))) |
| 00:29 | clojurebot | Execution Timed Out |
| 00:29 | TEttinger | ha! |
| 00:29 | dsrx | ,(launch-missiles) |
| 00:29 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: launch-missiles in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 00:30 | ztellman | TEttinger: sometimes you need to just coerce, for instance if you're pulling numbers out of a Clojure data structure, but often that's not the case |
| 00:30 | devn | cark: toldyaso |
| 00:30 | ztellman | also, it's not clear at compile time whether it should be integer or floating point arithmetic |
| 00:30 | cark | devn make it smaller and do it again and again =) |
| 00:30 | ztellman | you'd have to do that at runtime, which is effectively what Clojure already doe |
| 00:30 | ztellman | does* |
| 00:31 | devn | cark: your turn. i created the PoC, my work here is done. :) |
| 00:31 | cark | devn : i'm a pacifist at heart, let the poor clojurebot live |
| 00:31 | TEttinger | ztellman, that's why I chose a different fn name |
| 00:31 | cark | ~botsnack |
| 00:31 | clojurebot | Thanks! Can I have chocolate next time |
| 00:31 | ztellman | it's a valid approach in some cases, but not all |
| 00:32 | devn | Do you guys know of any interesting ways to capture ->fooBar and map->fooBar when (defrecord fooBar []) is defined? |
| 00:32 | ztellman | in a lot of cases it would just be papering over the underlying issues |
| 00:32 | ztellman | devn: capture how? |
| 00:33 | ztellman | or rather, in what sense? |
| 00:33 | devn | that's the question, i suppose. kovas posted about not being able to programatically find map->fooBar when given fooBar. |
| 00:33 | devn | without string munging, that is |
| 00:34 | ztellman | string munging is valid |
| 00:34 | devn | ,(map second (filter #(= 'clojure.core/declare (when (coll? %) (first %))) (macroexpand-1 '(defrecord fooBaz [x y z])))) |
| 00:34 | clojurebot | (->fooBaz map->fooBaz) |
| 00:34 | ztellman | and the prize for most fragile solution goes to... |
| 00:34 | devn | that was my thought, but yeah, i suppose munging is just fine |
| 00:35 | devn | hahaha |
| 00:35 | devn | ztellman: *flick* |
| 00:35 | devn | there are 100 ways to find it |
| 00:35 | devn | i was just curious what clever sorts of things people would come up with |
| 00:36 | joshuafcole | Is there a simple way to test whether an expression supports a particular protocol? (e.g. ISeq?). Currently I'm using a condp statement to compare against known types, but that's awfully verbose and it doesn't support duck typing (when all the underlying mechanisms do) |
| 00:36 | devn | joshuafcole: #'clojure.core/satisfies? |
| 00:36 | joshuafcole | I'm hoping for something core (such that it would be applicable to cljs) |
| 00:36 | joshuafcole | Oh, awesome! I'll check it out |
| 00:36 | joshuafcole | thanks |
| 00:37 | devn | joshuafcole: there's also extends? and implements? |
| 00:39 | devn | ztellman: thanks for collection-check |
| 00:39 | ztellman | devn: oh, you used it? |
| 00:39 | ztellman | what for? |
| 00:42 | maravillas | dsrx: you're using cider/nrepl? have you looked for your output in *nrepl-server*? |
| 00:44 | TEttinger | ztellman, I guess I'm not entirely sure what causes reflection in the first place. (def width (long 33)), (- width 2) seems to cause a warning -- do you know why? |
| 00:44 | devn | ztellman: i was messing around with making an ordered invokable map. in general i just appreciate the lib because it provides a certain level of documentation |
| 00:44 | TEttinger | would (- width (long 2)) change it? |
| 00:44 | ztellman | TEttinger it might make more sense if you used no.disassemble to look at what that actually turns into |
| 00:45 | ztellman | but in this case, 'width' isn't known to be a long |
| 00:45 | ztellman | it might change later |
| 00:45 | ztellman | so any code that references it gets the value out of the var, and it comes out as an Object |
| 00:45 | ztellman | (- (long width) 2) fixes it |
| 00:45 | devn | ztellman: a CsvRecord type to allow for transformations while maintaining the header order |
| 00:46 | ztellman | devn: strongly encourage using potemkin unless you get hives thinking about that as a dependency |
| 00:46 | ztellman | makes it infinitely easier to do map variants |
| 00:46 | devn | ztellman: yes, i've seen you messing with generating nonvariadic invocations and what-not |
| 00:47 | TEttinger | ztellman, so you said I should prefer... "ideally you change something upstream", but if def makes an Object... |
| 00:47 | devn | ztellman: potemkin.types is what i guess i'm referring to |
| 00:48 | TEttinger | would there be trouble if I wrapped the whole file in a toplevel let? |
| 00:48 | ztellman | TEttinger if it's really just a value, (def ^:const width 2) will just put '2' wherever you use the var |
| 00:49 | TEttinger | that's much better |
| 00:49 | devn | ztellman: alan dipert and i were chatting and he got me into this whole invokable thing. i guess i hadn't noticed, but clojure is different from other lisps in that it expands invokability to maps, vectors, etc. |
| 00:50 | ztellman | it's a fun thing to play around with, it's just a bear to make a new data structure that quacks like a Clojure data structure |
| 00:51 | devn | ztellman: yeah, i am more in "fun time" mode right now with what im working on |
| 00:51 | devn | but i still appreciate coll-check as a template for checking your own stuff works with clojure proper |
| 00:52 | ztellman | ha, yeah, I found issues with everything I had written beforehand |
| 00:52 | devn | that's just what simple-check does to you in general |
| 00:52 | dsrx | maravillas: aha! thank you |
| 00:52 | devn | i was messing with order on a set of fns that should have been idempotent over maps |
| 00:52 | dsrx | (inc maravillas) |
| 00:52 | lazybot | ⇒ 2 |
| 00:53 | maravillas | welcome! |
| 00:53 | devn | aka #'this #'that #'another were all fns which operated on {...} |
| 00:53 | devn | and no matter the order, they should all have produced Result: {...} |
| 00:53 | devn | simple-check just made me sad |
| 00:53 | devn | it's like lein-pedantic |
| 00:53 | devn | prior to deps tree |
| 00:53 | devn | it could just be incredibly sad to run sometimes |
| 00:57 | devn | ztellman: which reminds me. i think i'm going to work on a tool to generate tests based on simple-check gen/any test results. |
| 00:58 | devn | a repl-driven sort of thing where you can optionally nail down input shapes and output shapes when it starts to become clear that fn isn't going anywhere |
| 01:00 | ztellman | that's a big space to explore blind |
| 01:01 | ztellman | I'd imagine you need some sort of hinting |
| 01:01 | devn | yeah, maybe. i think in general my mind is just wandering to: where all all the sub-repl envs? |
| 01:01 | devn | s/all all/are all/ |
| 01:02 | devn | i want to do: (hmmmm '(my-fn 1)) |
| 01:03 | devn | and live in a separate development repl for a moment to analyze my code, profile it, etc. |
| 01:03 | devn | sort of a dashboard for repl-based code analysis |
| 01:09 | egghead | if there is a cljs lib I want to use that isn't published to clojars, how can I install it for use locally? |
| 01:10 | egghead | (assuming I have access to the project from github) |
| 01:10 | dsrx | egghead: clone the git repo, lein install |
| 01:10 | dsrx | should work right? |
| 01:10 | egghead | probably... |
| 01:11 | noonian | yep |
| 01:14 | egghead | ah okay, I just had to do a cljsbuild clean too |
| 01:14 | egghead | thx dsrx noonian |
| 01:21 | dsrx | np |
| 03:35 | d11wtq | Can I get javadoc info from inside the REPL, without opening a browser? |
| 03:38 | xuser | d11wtq: with the lein repl you can |
| 03:40 | xuser | d11wtq: oh never mind, haven't tried it :D |
| 03:41 | xuser | though (javadoc) could do it |
| 03:42 | d11wtq | xuser: Yeah, #'javadoc tries to open your browser, which doesn't work in a headless environment (like SSH'd into a server) |
| 04:32 | deadghost | http://i.imgur.com/yUfD59c.png |
| 04:32 | deadghost | just wanted to show off my crappy compojure/enlive app before going to bed |
| 04:46 | logic_prog | is there a way, in cljs, to register a function to be called when a channel is gc-ed ? |
| 06:20 | AeroNotix | ,(go (prn (+ 1 1))) |
| 06:20 | clojurebot | #<OutOfMemoryError java.lang.OutOfMemoryError: PermGen space> |
| 06:23 | cark | devn : see that ? |
| 06:24 | cark | ,(+ 1 2) |
| 06:24 | clojurebot | 3 |
| 06:24 | cark | mhh |
| 06:24 | cark | ,(go 1) |
| 06:24 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: go in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 06:24 | AeroNotix | ,(go (prn (+ 1 1))) |
| 06:24 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: go in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 06:24 | AeroNotix | gremlins |
| 06:25 | cark | restarted maybe |
| 06:26 | cark | a defracord would go to permgen wouldn't it ? |
| 06:26 | cark | defrecord |
| 06:26 | cark | ,(defrecor someRecord []) |
| 06:26 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: defrecor in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 06:26 | cark | ,(defrecord someRecord []) |
| 06:26 | clojurebot | sandbox.someRecord |
| 06:26 | AeroNotix | I have 1.5.1 but I don't have clojure.core.async, do I need to download it separately? |
| 06:27 | AeroNotix | (require '[clojure.core.async :as async :refer :all]) |
| 06:27 | AeroNotix | is how I'm trying to use it |
| 06:27 | cark | yes you need to add it to your project |
| 06:27 | AeroNotix | ok |
| 08:11 | wei__ | mini puzzle for you guys. I have a list of booleans and want to transform it to take a value from list A if it's true, and a value from list B if it's false. so for example, (take-multiplex [false true false true true true] (range) [:a :b :c :d :e :f :g]) should give me [:a 1 :b 2 3 4]. four from list A and two from list B. |
| 08:13 | wei__ | ^ actually, the result should be [:a 0 :b 1 2 3] since range starts from 0 |
| 08:24 | gfredericks | ,(defn tm [[b & bs' :as bs] [x & xs' :as xs] [y & ys' :as ys]] (lazy-seq (when (seq bs) (if b (cons x (tm bs' xs' ys)) (cons y (tm bs' xs ys')))))) |
| 08:24 | clojurebot | #'sandbox/tm |
| 08:24 | wei__ | here's what I got, maybe there's a better way using seq functions rather than recursion. https://www.refheap.com/27931 |
| 08:24 | gfredericks | ,(tm [false true false true true true] (range) [:a :b :c :d :e :f :g]) |
| 08:24 | clojurebot | (:a 0 :b 1 2 ...) |
| 08:25 | wei__ | ah, lazy-seq. i always forget about that one |
| 08:25 | gfredericks | wei__: I think this is too weird for seq fns, but lazyseq+recursion is better than recur |
| 08:26 | wei__ | i like seq functions because they're more clojurey, but is there an actual performance difference? |
| 08:26 | gfredericks | I'm not sure what you're comparing to what |
| 08:26 | wei__ | your solution vs mine |
| 08:27 | gfredericks | I don't think there's an assymptotic difference. You can plug them into criterium to see |
| 08:27 | gfredericks | remembering that mine is lazy so you might want to doall or something |
| 08:28 | wei__ | laziness is a a nice feature |
| 08:28 | wei__ | anyways thanks |
| 08:28 | wei__ | (inc gfredericks) |
| 08:28 | lazybot | ⇒ 38 |
| 08:29 | wei__ | gluck with your kid |
| 08:30 | voldyman | hey guys, i am learning compojure my routes look like http://pastie.org/8668891 is this the right way? |
| 08:58 | gfredericks | voldyman: no |
| 08:59 | gfredericks | well depends on what the dummy handler stuff means |
| 09:08 | sobel | so, i'm selfteaching clojure with http://www.braveclojure.com/do-things/ but i am wondering if there are better tutorials |
| 09:09 | sobel | i'm also wondering just what the effort level is like for transfering my clojure knowledge to other lisps like Clozure |
| 09:10 | voldyman | sobel: try braveclojure its a good resource |
| 09:10 | sobel | voldyman: i do like it, and i'm getting through the syntax and types pretty easily |
| 09:16 | voldyman | gfredericks: the handler fn s take the values from params and would fetch data from the sql db |
| 09:21 | gfredericks | voldyman: you need to handle it inline or call your functions, not just mention them |
| 09:23 | voldyman | gfredericks: hmm, rightnow the functions are being automatically called with the request map, to call them i would have to destructure them first then pass as argument {subject :as request} (subject-handler request subject) ?? |
| 09:23 | lazybot | voldyman: Uh, no. Why would you even ask? |
| 09:23 | voldyman | lazybot: because i am learning, and most sample code does it differently |
| 09:23 | dsrx | lol... rude, lazybot |
| 09:23 | gfredericks | voldyman: I'm surprised the functions are being called |
| 09:24 | sobel | is it normal to go code-blind with lisp really easily, coming from a java/C++ background? |
| 09:25 | hyPiRion | voldyman: lazybot is just a bot reacting to ?? and ???, just fyi. Right, lazybot??? |
| 09:25 | lazybot | hyPiRion: Yes, 100% for sure. |
| 09:25 | sobel | i think my eyes are looking for ECMA style blocks and just not finding them |
| 09:25 | voldyman | sobel: lisp's are like LSD for nerds. first you don't understand whats happening and when you do its a whole other world. |
| 09:26 | sobel | voldyman: i'm familiar with the concept.. just trying to figure out how long i'll feel dyslexic reading functional code |
| 09:28 | voldyman | after reading just one tutorial i began to understand clojure, but with am totally lost after trying to read lots haskell |
| 09:28 | sobel | i'm trying to get my head around side-effect free programming |
| 09:28 | sobel | i hope/suspect that is the conceptual leap i need to make |
| 09:37 | jonathanj | i wonder if anyone else thinks it's weird that "(inc x)" mutates x :P |
| 09:38 | jonathanj | in the context of the bot, i mean |
| 09:38 | gfredericks | mutable numbers! |
| 09:39 | gfredericks | $google github flexnum |
| 09:39 | lazybot | [CSS3 Flexible Box Layout Explained | Smashing Coding] http://coding.smashingmagazine.com/2011/09/19/css3-flexible-box-layout-explained/ |
| 09:39 | jonathanj | haha |
| 09:39 | gfredericks | $google github fredericksgary flexnum |
| 09:40 | gfredericks | bah |
| 09:46 | sobel | ok, i already like lisping in clojure. where's the fast-forward tutorial for a seasoned java developer? i understand all the OS interfaces are (familiar) java classes |
| 09:48 | gfredericks | clojure.org maybe? :) |
| 09:48 | RickInAtlanta | have you read the book "the joy of clojure"? |
| 09:48 | sobel | i've tried nada. that's why i'm asking around here. |
| 09:49 | Phonatacid | oh hi. I think I need some advice in designing a simple "debugger" for clojure. Motivation : reading clojure code you wrote can be pretty difficult. Usually, when I come back to code I wrote a long time ago, I tend to commentize all the forms in the concerned function and then decommentize them gradually, just to see how the "data flow" evolves through the function. Goal : my goal is to write a tool that will record all |
| 09:49 | Phonatacid | values of intermediate forms so that I don't have to apply the debugging scheme described above. Instead I would simply hover the mouse over the form via a web interface / text-editor plugin and have the intermediate values displayed in a popup window. Approach : I know this can turn out to be a pretty complex problem to solve. However I just intend to hack something very simple in just a couple hundreds lines. Problem : |
| 09:49 | Phonatacid | I'm not doing static analysis (but might be forced to) should I use clojure.tools.analyzer ? |
| 09:49 | sobel | well, i've bootstrapped syntax with braveclojure and will keep that one handy for a little while but i'm short on details needed to use arbitrary java classes |
| 09:51 | RickInAtlanta | sobel last week I did a short blog post where I just walked through some examples of using java classes to access microsoft's blob store. will let you see java interop in action. onbeyondlambda.blogspot.com |
| 09:51 | RickInAtlanta | I don't know if it is exactly what you are looking for, but its a start |
| 09:51 | clojurebot | In Ordnung |
| 09:55 | ornicar | hello, I'm a scala dev giving clojure a try! |
| 09:55 | RickInAtlanta | hello |
| 09:55 | ornicar | I'm coding a project involving a HTTP/JSON client now |
| 09:56 | ornicar | I read the great lein tutorial https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md#readme and it leaves me with one question |
| 09:56 | ornicar | how do you reload the code in lein, after you save your .clj file? |
| 09:57 | sobel | RickInAtlanta: thanks, i'm taking a look at it. jdbc is my first target, so that's not too far off |
| 09:59 | RickInAtlanta | sobel: this page on clojure.org walks through interop http://clojure.org/java_interop |
| 09:59 | Phonatacid | ornicar: (use 'my-project.core :reload) |
| 09:59 | ornicar | thanks, trying that now |
| 09:59 | Phonatacid | (besides : "mais ou et donc or ni car" ?) |
| 10:00 | Phonatacid | don't forget the apostrophe at the beginning of the namespace name. :reload-all also reload used/required namespaces |
| 10:00 | ornicar | works \o/ |
| 10:01 | ornicar | I'm used to sbt (scala build tool) automatically applying changes on file save, tho. I'm gonna give https://github.com/paraseba/lein-reload a try. |
| 10:02 | ornicar | I'm so excited to finally discover lisp :) |
| 10:02 | sobel | RickInAtlanta: thanks, both those refs are hitting the spot |
| 10:03 | sobel | it's gonna be weird getting used to chopping up java classpaths with / |
| 10:03 | sobel | (outside of the filesystem or jarpath) |
| 10:04 | Phonatacid | I'm not sure to which extent scala is dynamic, but function definition actually work like side-effect inducing functions. So if you load a namespace, delete a function in the associated file, then reload the namespace, the deleted function will still be there ine memory. THis sort of repl-ly behavior can also induce namespace conflicts. Usually, exiting & restarting the repl works. |
| 10:06 | RickInAtlanta | sobel for jdbc you might look at https://github.com/clojure/java.jdbc |
| 10:07 | sobel | that looks like it'll be handy |
| 10:49 | sobel | other than the obvious java interop stuff, how portable is clojure code to other lisps? |
| 10:50 | borkdude | sobel it's not very portable I think. Clojure is clojure. |
| 10:51 | borkdude | sobel it has its own idea about immutability, etc |
| 10:52 | sobel | interesting. good to know as a new-to-lisp person. |
| 10:52 | sobel | clojure is my first |
| 10:52 | borkdude | nice choice |
| 10:54 | RickInAtlanta | sobel there are a lot of syntax differences too. |
| 10:55 | RickInAtlanta | first and rest in clojure are car and cdr in lisp and scheme |
| 10:55 | sobel | is there any "common ground" for things like library implementations of extremely common/popular algorithms? |
| 10:56 | RickInAtlanta | most libraries that you will want to use are stored in a repository called clojars. leiningen searches clojars and maven for dependencies |
| 10:57 | RickInAtlanta | what I do is google what I am looking for which usually takes me to libraries on github |
| 10:57 | sobel | ok, i am aware of lein and clojars. i guess what i'm asking is, is there any notation or syntax limitation that is used to convey portable lisp or is that just right out with syntax differences? |
| 10:58 | RickInAtlanta | sobel I would say it is right out. |
| 10:58 | sobel | cool |
| 10:58 | RickInAtlanta | A lot of the ideas from lisp are very useful to understand how to do things |
| 10:59 | RickInAtlanta | however one of the things clojure does is it provides a standard way of doing things. particularly the sequence functions |
| 11:00 | RickInAtlanta | I haven't read too deeply into lisp stuff, but what i have seen, seems like "ok, here is how you do this with recursion, and here is how you can generalize that into working with an arbitrary function on an arbitrary list ..." where as Clojure has aloready done that with seq's |
| 11:01 | sobel | huh. sounds pretty useful. |
| 11:02 | RickInAtlanta | yeah, I spent some time going through OnLisp (only made it about 1/3 of the way through) and translating the examples into Clojure. It made me really happy I started with Clojure |
| 11:02 | sobel | ah, persistent immutable generators |
| 11:03 | sobel | everything i learned about sql lately has impressed on me the value of MVCC |
| 11:05 | sobel | no. wtf, must copy source array to get full immutability? |
| 11:06 | sobel | is there a copy-on-write data type? |
| 11:08 | RickInAtlanta | not sure what you mean. clojure's data structures are immutable, java arrays are not. |
| 11:10 | sobel | nevermind, i think nonlazy seqs are what i need there |
| 11:11 | llasram | sobel: What are you trying to do? |
| 11:11 | sobel | llasram: ultimately, learn to think about data concurrency in lisp the same way i do in sql |
| 11:14 | llasram | Huh |
| 11:17 | llasram | Well, the first step is to probably to stop worrying about thinking about it as "in Lisp." Pretty much all Lisp-family languages have in common is the s-expression syntax, homoiconicity of those s-expressions, and some aesthetics |
| 11:19 | llasram | But I'm not sure what you mean by the comparison to SQL |
| 11:19 | sobel | specifically MVCC |
| 11:20 | llasram | Yeah, that's not really a thing at the language level |
| 11:20 | sobel | can i lock a var in lisp such that another thread waits? |
| 11:20 | sobel | i'm sure that's the wrong mindset but i don't know the right one |
| 11:21 | RickInAtlanta | sobel: ask about clojure, not lisp. you can do mvcc in clojure |
| 11:22 | RickInAtlanta | a "ref" in clojure is a data type that can only be modified inside a transaciton |
| 11:22 | llasram | Clojure has it's own collection of "reference types" mostly implemented in terms of a software transactional memory system, which does internally leverage an MVCC implementation |
| 11:22 | sobel | awesome |
| 11:22 | llasram | But I have never seen real code use it |
| 11:22 | llasram | http://clojure.org/concurrent_programming |
| 11:23 | llasram | Has a big chunk of the details if that's what you care abotu |
| 11:23 | sobel | thanks, i do :) |
| 11:23 | llasram | kk |
| 11:25 | RickInAtlanta | sobel pluralsight.com has a courese on clojure concurrency. I think you can get a free trial there to check it out |
| 11:26 | RickInAtlanta | it is several years old, so it won't have things like core.async but it does cover vars, refs atoms and agents |
| 11:27 | sobel | knowing it's language-embedded tells me everything i need |
| 11:28 | dabd | why am I getting a NPE here? |
| 11:28 | dabd | ,(update-in [0 1 2] [0 1] inc) |
| 11:28 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 11:28 | dabd | shouldn't the second argument be a list of keys? |
| 11:29 | sobel | ,(System/getProperty "java.vm.version") |
| 11:29 | clojurebot | #<SecurityException java.lang.SecurityException: denied> |
| 11:29 | sobel | haha |
| 11:30 | sobel | nicely secured |
| 11:31 | RickInAtlanta | ,(update-in [0 [0 1 2] 2] [1 2] inc) |
| 11:31 | clojurebot | [0 [0 1 3] 2] |
| 11:32 | AeroNotix | ,(go (+ 1 1)) |
| 11:32 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: go in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 11:32 | AeroNotix | ,(clojure.core.async/go (+ 1 1)) |
| 11:32 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.core.async> |
| 11:32 | AeroNotix | YEH WTVR |
| 11:32 | insamniac | ,(update-in [0 [0 1 2] 2] [1 1] inc) |
| 11:32 | clojurebot | [0 [0 2 2] 2] |
| 11:32 | dabd | right it has to be nested |
| 11:32 | insamniac | oh i get it |
| 11:33 | ponpal | ,(map inc [1336 41]) |
| 11:33 | clojurebot | (1337 42) |
| 11:33 | sobel | ,(inc 31336) |
| 11:33 | clojurebot | 31337 |
| 11:33 | sobel | \o/ |
| 11:33 | jonasen | dnolen: how close is https://www.refheap.com/27985 to how cursors work in Om? |
| 11:36 | dnolen | jonasen: that's the basic idea w/o optimizations & supporting more collection operations |
| 11:37 | jonasen | dnolen: cool! Then I think I understand a little better how Om works. Thanks! |
| 11:38 | jonasen | Your cursor idea could probably be useful outside of Om also |
| 11:42 | dnolen | jonasen: yes I think so too. It really isn't so different from the getter/setter aspect of lenses. |
| 11:43 | RickInAtlanta | I am working through the reasond schemer, and I am having trouble translating ch 3 # 45. I think i have this line wrong (loto ((g g) (e w) (x y) . z)) |
| 11:44 | RickInAtlanta | my version is (loto (lcons [['g 'g] ['e w] [x y]] z)) |
| 11:45 | RickInAtlanta | can I not replace lists with vectors? |
| 11:46 | algernon | RickInAtlanta: try (loto (lcons ['g 'g] (lcons ['e w] (lcons x y))) z) |
| 11:46 | RickInAtlanta | for simpler expresions, like (loto (lcons ['g 'g] z)) it seems to wrok |
| 11:48 | lvh | j #python |
| 11:48 | lvh | Oops. |
| 11:49 | algernon | RickInAtlanta: lcons takes two args, a head and a tail. (lcons [['g 'g] ['e w] [x y]] z)) => (((g g) (e w) (x y)) . z) |
| 11:51 | RickInAtlanta | algernon yeah, so I think the two ways you expressed it are the same |
| 11:51 | AeroNotix | how does the scheduling work with go blocks? |
| 11:51 | AeroNotix | I've got some code and it seems my go blocks are not executing |
| 11:52 | RickInAtlanta | algernon: maybe my problem is in the next line (== (w (x y) z) r))) |
| 11:52 | RickInAtlanta | I tried writing that with vectors, I am going to try rewriting with lcons |
| 11:53 | algernon | that line seems fine. |
| 11:53 | algernon | well, mostly, a few ' here and there. |
| 11:53 | algernon | or, no, they're all LVars, nvm. that line should be correct with vectors. |
| 11:54 | RickInAtlanta | algernon I think that is my problem, figuring out how to prevent the list from being evaluated as a function, but still allowing w x y z to be evaluated as lvars |
| 11:54 | algernon | vectors |
| 11:54 | RickInAtlanta | yeah, as vectors, doesn't work |
| 11:54 | algernon | because your loto line is wrong :) |
| 12:03 | RickInAtlanta | algernon: I appreciate the help... wondering now if I implimented loto wrong. More coffee, then lots of digging :) |
| 12:04 | Raynes | devn: ping |
| 12:05 | algernon | RickInAtlanta: how's your loto line looking now? is it still (loto (lcons [['g 'g] ['e w] [x y]] z)) ? |
| 12:05 | RickInAtlanta | I tried it like that, and as the nested lcons like you suggested |
| 12:06 | RickInAtlanta | Now I am trying expressions combining loto and == to see if I can find where the disconnect is |
| 12:06 | algernon | mhm, in that case your loto may be wrong, yes. the nested lcons should work. |
| 12:06 | algernon | I'd try running the command, see what it returns, and compare it to the expected one, by hand |
| 12:07 | RickInAtlanta | yeah, just breaking it into the small pieces and following all the steps. = good learning |
| 12:10 | devn | Raynes: pong |
| 12:11 | Raynes | devn: It never occurred to me that you lived in Madison before. You should hang out with a friend of mine, Erik Price, who goes to college there. |
| 12:11 | Raynes | <3 |
| 12:11 | devn | I will hang out with this friend of yours. |
| 12:12 | Raynes | I'll tell him I found him a new friend. |
| 12:12 | Raynes | ;p |
| 12:17 | devn | my internets are extremely slow |
| 12:34 | gfredericks | Madison is the Chicago of Chicago |
| 12:38 | AeroNotix | https://gist.github.com/AeroNotix/9927cc922e8c40c521fa I'm tring to spawn off a few goroutines which will launch filewatchers on directories. Not all of the watchers are being enabled. Can anyone see anything glaringly wrong with this? I wrote it pretty much how I would use Go's goroutines.. |
| 12:43 | devn | gfredericks: heh |
| 13:03 | AeroNotix | any ideas ^^ |
| 13:03 | gfredericks | AeroNotix: does awizo/attach-handler block? |
| 13:04 | AeroNotix | gfredericks: yes |
| 13:05 | gfredericks | this is not the intended use of go afaik |
| 13:05 | AeroNotix | Then why do people say it's used like the `go' statement in Go? |
| 13:06 | AeroNotix | How are they scheduled? |
| 13:06 | AeroNotix | preemptively or co-operatively ? |
| 13:06 | gfredericks | on a thread pool |
| 13:06 | gfredericks | and the point is that lexically inside the go macro you are using things like >! and <! |
| 13:06 | gfredericks | which is where the scheduling magic occurs |
| 13:06 | AeroNotix | Do these invoke cooperative scheduling? |
| 13:07 | gfredericks | in your case there is no scheduling |
| 13:07 | gfredericks | all you're doing is taking a thread pool thread and keeping it |
| 13:07 | gfredericks | so when all the threads are used up you can't run any more code |
| 13:07 | AeroNotix | Well, it'd be great if the docs mentioned this |
| 13:07 | AeroNotix | All the videos/talks lead me to believe it was semantically the same as Go's concurrency |
| 13:08 | AeroNotix | ,(doc clojure.core.async/go) |
| 13:08 | clojurebot | Gabh mo leithscéal? |
| 13:08 | AeroNotix | :/ |
| 13:09 | gfredericks | AeroNotix: the docs sort of mention it |
| 13:09 | gfredericks | keyword is "visible" |
| 13:10 | AeroNotix | So, what are my options for user-space threading in Clojure? |
| 13:10 | AeroNotix | pre-emptively scheduled |
| 13:10 | AeroNotix | (last |
| 13:10 | AeroNotix | (last thing is not 100% necessary but would be nice) |
| 13:10 | gfredericks | this watcher lib can only work by blocking a thread? |
| 13:10 | AeroNotix | gfredericks: you can poll, too |
| 13:12 | gfredericks | oh this is your lib? |
| 13:15 | gfredericks | so the lib requires that to watch N files you need N threads polling |
| 13:15 | gfredericks | that might be the place to tweak |
| 13:16 | AeroNotix | gfredericks: eugh |
| 13:17 | gfredericks | clojure doesn't have a way to grope the JVM internals and give you transparent green threads. async/go is just a macro that looks at the body of the macro and does a fancy transformation into a state machine |
| 13:17 | gfredericks | then those state machines are run on thread pools |
| 13:20 | gfredericks | I would either incorporate core.async into the lib directly, or have it deal with handler functions from another thread so that it can be easily wrapped with async channel logic |
| 13:21 | gfredericks | http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html |
| 13:32 | Cigitia | I have a question—let’s say I have a macro: (defmacro aaa [expr] (if (-> expr first (= `clojure.string/lower-case)) (first expr) `(+ 5 3))). |
| 13:32 | Cigitia | Then (aaa (clojure.string/lower-case)) will expand to clojure.string/lower-case, which is what I want. |
| 13:33 | Cigitia | But if I do (require '[clojure.string :as string]), I’d like (aaa (string/lower-case)) to expand into the same…but it’ll expand into (+ 5 3) instead, since string/lower-case does no equal clojure.string/lower-case. |
| 13:34 | Cigitia | Is it possible for the (-> expr first (= `clojure.string/lower-case)) to determine that string/lower-case is the same as clojure.string/lower-case? |
| 13:34 | andyf | Cigitia: Maybe a use of resolve on the symbol will achieve what you want, and then compare the return value of resolve against the var #'clojure.string/lower-case ? |
| 13:35 | Cigitia | Hmm… |
| 13:36 | Cigitia | resolve seems to return a var. The problem with that, I think, is that I’m using this macro inside ClojureScript, whose vars I don’t think are available in Clojure macro expansion. |
| 13:37 | Cigitia | Is there a way to resolve the symbol into another symbol during macro expansion, but inside a ClojureScript namespace using its namespace aliases? Maybe some sort of double quoting–splicing thing, but I’m not sure… |
| 13:46 | gfredericks | Cigitia: I'm curious what you're trying to achieve |
| 13:49 | Cigitia | gfredericks: I have a macro that wraps an expression in an outer expression. But the wrapping is unnecessary when the inner expression is a call on a certain function; I want the macro to just return the inner expression itself when it starts with that function’s symbol, whether it’s namespace-qualified or not. |
| 13:51 | gfredericks | that sounds brittle/difficult/impossible to do at macroexpansion time |
| 13:52 | gfredericks | at least if you allow edge cases |
| 13:52 | gfredericks | wait scratch that; the thing I was thinking of is not |
| 13:52 | Cigitia | Mm, yes. I think I might need to do something like (defmacro aaa [expr] `(let [inner-result# ~expr] (if (a-result-of-that-special-function? inner-result#) inner-result# (outer-wrapping inner-result#)), somehow using a new a-result-of-that-special-function? function, heh. |
| 13:53 | Cigitia | Er, that should be closed with a few more parentheses, heh. |
| 13:53 | gfredericks | doing this at runtime is not acceptable? |
| 13:55 | Cigitia | The reason why I’m not doing that is because that special function that I want to detect to prevent a redundant wrapping—it itself returns a function at runtime, so I can’t distinguish its results from other expressions at runtime. |
| 13:55 | Cigitia | I can modify that special function to return a data structure, though, which seems to be necessary in this case. |
| 13:56 | gfredericks | you can also put metadata on functions if that helps |
| 13:58 | Cigitia | Oh, that’s right; that should work. Thanks a lot! |
| 13:58 | gfredericks | np |
| 13:58 | gfredericks | another win for the first rule of macro club |
| 14:00 | Cigitia | I still need to make it a macro because the inner expression, when it needs to be wrapped, must not be evaluated at runtime before being wrapped. But I can still do the testing for whether it needs to be wrapped at all at runtime. |
| 14:00 | Cigitia | Right, this works; thanks again. |
| 14:12 | dkinzer | I'm seeing an unexpected behavior in how the repl behaves when I initialize one of two different forms which on the face of it look like they are equivalent. In one case I use (do ...) and in the other I use (doseq ...). These don't behave the same even though though I'm passing what appear to be equivalent expressions in the body: https://gist.github.com/dkinzer/8637554 |
| 14:12 | darklajid | If I have gazillion strings (and most of them are the same), do I need to nudge clojure to intern these strings to save memory? Is that even possible? |
| 14:13 | gfredericks | darklajid: (.intern s) should return a canonical object |
| 14:13 | AimHere | dkinzer, doseq and do do very different things |
| 14:14 | gfredericks | dkinzer: oh man this is slippery |
| 14:15 | AimHere | dkinzer, hmmm, could it be that ns is a macro not a function? |
| 14:15 | dkinzer | AimHere: so for (doseq) I"m under the imprssion that I pass it a list and I can run an expression with side effects in the body expression. |
| 14:15 | AimHere | I did try (doseq [i <stuff>] (ns i)) and it namespaced me to 'i' which suggests that it doesn't evaluate the first argument at all |
| 14:16 | dkinzer | AimHere: It could be. I tried looking ath repl.clj on lein code but I couldn't really decipher it. |
| 14:16 | clojurebot | It's greek to me. |
| 14:16 | gfredericks | yeah ns is a macro so that kind of programmatic use is not going to work |
| 14:17 | dkinzer | AimHere: yeah but then I tried (doall (for ..)) which apparently is supposed to force an evaluation and I get the same issue. |
| 14:17 | gfredericks | dkinzer: that doseq form won't work in a repl either |
| 14:17 | RickInAtlanta | ,(doc ns) |
| 14:17 | clojurebot | "([name docstring? attr-map? references*]); Sets *ns* to the namespace named by name (unevaluated), creating it if needed. references can be zero or more of: (:refer-clojure ...) (:require ...) (:use ...) (:import ...) (:load ...) (:gen-class) with the syntax of refer-clojure/require/use/import/load/gen-class respectively, except the arguments are unevaluated and need not be quoted. (:gen-class ..... |
| 14:17 | AimHere | Could you try writing a macro that evaluates to a list of (ns foo (whatever)) calls? |
| 14:17 | egghead | AimHere: what do you expect that to mean? |
| 14:18 | dkinzer | gfredericks: What I don't understand is why the (do) expression is working. |
| 14:18 | egghead | are you trying to define many namespaces in a single form? clj is one ns per file |
| 14:19 | dkinzer | gfredericks: Shouldn't they both fail? The are essentially doing the same thing. |
| 14:19 | clojurebot | Gabh mo leithscéal? |
| 14:19 | gfredericks | dkinzer: because you have the ns name directly in the ns form in that case |
| 14:19 | gfredericks | dkinzer: this is confusing because of the difference between macros and functions |
| 14:20 | dkinzer | gfredericks: Yeah, but if I don't pass the name as a symbol in the (doseq) body then it throws. I have to pass it in as 'namespace |
| 14:21 | dkinzer | I would love to be able to use the (doseq) becuase without it I'm doing a bunch of repitive calls to (ns ) but with different arguments. It looks ugly. |
| 14:24 | pyrtsa | dkinzer: Did you check in-ns? |
| 14:24 | gfredericks | dkinzer: your goal is to have some special namespaces created every time your repl starts? |
| 14:24 | pyrtsa | ,(in-ns) |
| 14:24 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: > |
| 14:24 | pyrtsa | ,(doc in-ns) |
| 14:24 | clojurebot | "([name]); Sets *ns* to the namespace named by the symbol, creating it if needed." |
| 14:25 | dkinzer | pyrtsa: hmmm I don't remember. Maybe I'll give that a try. |
| 14:27 | dkinzer | gfredericks: Acutaly my goal is get the repl to work nicely with the clojure-koans and vim-fireplace. Using the (do) expression fixes the issue but it's not nice and I want to make sure that I can explain to the clojure-koans maintainer that I tried all the options. |
| 14:28 | dkinzer | gfredericks: one thing I tried that should have worked was to just add the (ns) expressios directly to the koan files but this only gets me half way. And the repl server still throws. |
| 14:29 | AeroNotix | gfredericks: sorry I didn't reply, power cut |
| 14:30 | AeroNotix | So, ok, I can rewrite all this to use purely channels with polling events. Thus allowing the go blocks to schedule |
| 14:30 | AeroNotix | Yeah I didn't know that the go blocks *required* channel reads to schedule. |
| 14:30 | AeroNotix | Go is a little similar (or at least) was in this regard. |
| 14:32 | gfredericks | ,(macroexpand-1 '(ns foo (:use bar))) |
| 14:32 | clojurebot | (do (clojure.core/in-ns (quote foo)) (clojure.core/with-loading-context (clojure.core/refer (quote clojure.core)) (clojure.core/use (quote bar))) (if (.equals (quote foo) (quote clojure.core)) nil (do (clojure.core/dosync (clojure.core/commute (clojure.core/deref (var clojure.core/*loaded-libs*)) clojure.core/conj (quote foo))) nil))) |
| 14:33 | gfredericks | dkinzer: why do those namespaces being created make the repl play nicely/ |
| 14:33 | gfredericks | ? |
| 14:36 | dkinzer | gfredericks: sorry was trying out (in-ns) wihtout luck. It throws. |
| 14:37 | dkinzer | gfredericks: For one there is a function defined in koan-engine.core called meditations that has to be in scope when any evaluation happens on a koan file via vim-fireplace. |
| 14:38 | gfredericks | are you creating one namespace per koan? |
| 14:38 | gfredericks | from the project.clj? |
| 14:39 | dkinzer | gfredericks: well.. that's only part of it. The weird thing is that I can get the same result if I add the (ns expression directly to the koan file). But what is different from the (do) expression as an option passed in via project.clj is that it wont throw even though technically all the koans should fail before they fixed. |
| 14:40 | gfredericks | you want an exception thrown from your repl init code? |
| 14:41 | dkinzer | gfredericks: The oppossite. I don't wan the exception thrown because this makes vim-fireplace fail completely. |
| 14:42 | dkinzer | gfredericks: So when it works properly I can for instance do a doc lookup from inside vim on any function. |
| 14:43 | abaker_ | say is there a way for incanter to deal with column names with spaces, e.g. in canter you can do (with-data … ($ [:col-name]), where col names are automatically turned to keywords. Works fine when the column name doesn't have a space, but not sure how it handles the keyword-ization of column names with spaces in it |
| 14:43 | dkinzer | gfredericks: The funnny thing is that I kind of stumbled onto the fix becuase it doesn't make any sense why it should matter where and how that (ns) expression is loaded. But for whatever reason it seems to. Though it's ugly. |
| 14:46 | dkinzer | gfredericks: I have pull request in at https://github.com/functional-koans/clojure-koans/pull/68 there is another one that addes the (ns) expressions direclty to the files but like I said that doesn't actually fix my issue. |
| 14:51 | gfredericks | dkinzer: so the intention is that the user opens a file and then evals the file to run the code? |
| 14:54 | dkinzer | gfredericks: yes that, which should fail (of course); but also be able to do partial evaluations which should pass (espcially... (doc ). It's the second part that fails with the former strategy but all works using just the (do) expression like I have in my PR |
| 14:54 | dkinzer | gfredericks++ |
| 14:55 | dkinzer | I'm not sure I'll get the bottom of this, but I'm very glad for your imput and for that matter everyone else who has tried helping me :) |
| 14:57 | RickInAtlanta | dkinzer: just want to make sure, you are trying to do an experiment to use repl with koans, and not just trying to do koans, right? |
| 14:57 | dkinzer | On a side note. I've noticed a lot of exception thrown that essentially say Class such and such could not be found when you pass it in a namespace. That confuses me becuase I thought there aren't any classes in clojure. |
| 14:58 | gfredericks | clojure's written in Java and does not try to hide it |
| 14:58 | dkinzer | RickInAtlanta: correct. |
| 14:59 | gfredericks | dkinzer: yeah your approach is ugly, as you noted, and haxy in ways that are hard to explain. I definitely expect there's something better but I'd have to understand the structure of the koans code better and how it's expected to be used |
| 14:59 | scape_ | anyone use korma? I don't understand how I am supposed to use the connection-pool function? I want to set idleConnectionTestPeriod manually |
| 15:00 | gfredericks | ,(class :foo) ;; dkinzer: classes in clojure :) |
| 15:00 | clojurebot | clojure.lang.Keyword |
| 15:02 | dkinzer | ,(class ns) |
| 15:02 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/ns, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:02 | dkinzer | ,(class in-ns) |
| 15:02 | clojurebot | clojure.lang.RT$1 |
| 15:02 | dkinzer | ,(class do) |
| 15:02 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: do in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:03 | dkinzer | ,(class doseq) |
| 15:03 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/doseq, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:03 | dkinzer | ,(class 1) |
| 15:03 | clojurebot | java.lang.Long |
| 15:03 | dkinzer | OK. |
| 15:11 | benmoss | anyone seen the "Uncaught TypeError: Cannot call method 'call' of undefined" exception coming from core.async in Clojurescript? |
| 15:11 | benmoss | i saw this thread but i double-checked my core.async and clojurescript versions and seem to both be latest |
| 15:11 | benmoss | https://groups.google.com/forum/#!msg/clojurescript/P902i4FKA4w/3ndE9ax62_gJ |
| 15:12 | benmoss | the stack trace just points to my (go (while true)) line that reads from the chan |
| 15:12 | dkinzer | gfredericks: Thanks for your help. I have to put this aside now. Cheers. |
| 15:12 | cark | benmoss: when i had this kind of error, a "lein cljsbuild clean" helpe |
| 15:13 | cark | helped |
| 15:13 | benmoss | ill try that |
| 15:13 | benmoss | i had tried just manually deleting the compiled JS |
| 15:13 | scape_ | anyone use korma? I don't understand how I am supposed to use the connection-pool function, I want to set idleConnectionTestPeriod manually |
| 15:13 | cark | benmoss: the cullprit is the out directory |
| 15:14 | benmoss | or 'target'? |
| 15:14 | cark | benmoss: depending on your setup =) |
| 15:15 | benmoss | hmm yeah i was deleting that too, and it still is erring after 'lein cljsbuild clean' |
| 15:16 | cark | oh but if you're refering to this post for latest verion, you're in the wrong |
| 15:16 | cark | the best way is to use search.maven.org |
| 15:16 | dnolen | benmoss: it nearly always means you've called something that doesn't exist, generally you get compiler warnings about this |
| 15:16 | benmoss | oh no i am not |
| 15:16 | cark | and search for latest clojurescript and core.async |
| 15:16 | benmoss | i'm on cljs 0.0-2138 and core.async 0.1.267.0-0d7780-alpha |
| 15:17 | benmoss | dnolen: no compiler warnings :( |
| 15:17 | dnolen | benmoss: post a complete gist of what isn't working for you |
| 15:17 | cark | benmoss: that's latest afaik |
| 15:19 | benmoss | dnolen: if you don't mind the whole repo, https://github.com/benmoss/chess . the repro step is just to click on any of the pieces |
| 15:19 | seancorfield | cljx question... just trying it out for the first time and when i run lein cljx, it tells me it is transforming my source but doesn't create the output files... |
| 15:19 | dnolen | benmoss: I'm going to look at a whole repo |
| 15:19 | dnolen | benmoss: you need to replicate this in the small |
| 15:19 | cark | dnolen: missing a not somewhere =) |
| 15:20 | benmoss | yeah i think you meant *not* going to look at a whole repo? |
| 15:20 | dnolen | benmoss: sorry I'm not going to look at something w/ that much context |
| 15:20 | benmoss | ok |
| 15:20 | benmoss | i understand its just effort to boil it down |
| 15:20 | seancorfield | here's my project tree and project.clj and the output of lein cljx https://www.refheap.com/28087 |
| 15:21 | cark | dnolen: while you're here, I wanted to ask you something. There is no extend in clojurescript, right ? |
| 15:21 | dnolen | cark: no |
| 15:21 | cark | dnolen: allright, i've seen there was something to do it on a per instance basis |
| 15:22 | cark | dnolen : actually forgot the name... but anyways, it doesn't work with function maps |
| 15:22 | cark | dnolen: so in clojurescript there is no way to do mixins ? |
| 15:22 | dnolen | cark: specify exists today, and the scope is much smaller than some of the things that were propose |
| 15:23 | cark | right that was specify =) ... but it doesn't work at all like extend, it's more like extend-type or extend-protocol for instances |
| 15:23 | dnolen | cark: exactly, there is nothing at all like extend in CLJS |
| 15:25 | cark | dnolen: allrigth, so how would it be possible to add code and functions to an instance (a per instance mixin if you will) ? |
| 15:25 | cark | dnolen: or is it what specify does ? |
| 15:25 | dnolen | cark: you can use specify provided the instance implements ICloneable |
| 15:26 | cark | dnolen: mhh i will consider that, thanks ! |
| 15:38 | benmoss | i knew it'd happen, but i attempted to boil down the bug and it doesn't happen anymore :) |
| 15:38 | RickInAtlanta | :) |
| 15:46 | benmoss | this is the fun "checkout to known good state, still broken" kind of bug |
| 15:47 | benmoss | hrmm |
| 15:52 | cark | dnolen: one last question, oes ICloneable nee to implement deep cloning or shallow is good enough ? |
| 15:52 | cark | need* |
| 15:53 | dnolen | cark: for Clojure data structures shallow cloning is deep cloning |
| 15:53 | dnolen | cark: JS data structures are out of luck |
| 15:53 | cark | dnolen: so I need to deep clone JS data ? |
| 15:53 | dnolen | cark: if you don't want bad things to happen in your program that don't make sense |
| 15:54 | cark | dnolen: what if it is newly created data, like in a make-my-data function |
| 15:54 | cark | everything fresh and new |
| 15:55 | dnolen | cark: it's fine if you can guarantee it won't leak |
| 15:55 | cark | dnolen: allright, thanks again |
| 15:55 | cark | dnolen: if you ever come to belgium i owe you at least a full barell of beer already |
| 15:56 | dnolen | cark: haha, will take you up on that if I'm ever in the neighborhood :) |
| 15:56 | cark | =) |
| 16:03 | seancorfield | no one using cljx? |
| 16:04 | seancorfield | would it be better to post the to clojure list or the clojurescript list do you think? |
| 16:11 | gufo__ | Hi ! can anybody give me a hint how to deal with unsigned int 32 in clojure ? ( the root of the question is icfp contest 2006, I'm trying to reimplement the vm) |
| 16:12 | dnolen | seancorfield: lots of people using cljx, best directed at cljs mailing list I think |
| 16:15 | egghead | if I have a seq of maps, what is the simplest way to provide a map to 'join' (filter) by ? |
| 16:15 | devn | is it possible to specify the type of keys a defrecord will use on creation? |
| 16:15 | devn | if you want new records to be created with keys as strings for instance |
| 16:15 | seancorfield | thanx dnolen - email sent... i'm sure i'm just doing something dumb |
| 16:16 | egghead | lemme take a peek seancorfield |
| 16:17 | egghead | ah seancorfield |
| 16:19 | egghead | seancorfield: I think you want to type 'lein cljx once' |
| 16:20 | seancorfield | no, chas spotted it on the mailing list immediately: my cljx file was named clj instead :( |
| 16:20 | egghead | oh, derp |
| 16:20 | seancorfield | I knew it would be a stupid mistake... Didn't think it would be _that_ stupid tho'! |
| 16:21 | egghead | dnolen: have you tried core.match with om yet? |
| 16:21 | seancorfield | My first foray into cljs with shared code! |
| 16:21 | dnolen | egghead: I haven't |
| 16:22 | egghead | seancorfield: i like cljx + prismatic, share resource schemas between client and server :) |
| 16:23 | piranha | dnolen: sorry, maybe I don't understand something, but it seems that in will-update next-props contain exactly the same data as (get-props owner), while I expected them to be different |
| 16:23 | skyl | (def stooges ["Moe" "Larry" "Curly" "Shemp"])(some #(instance? Number %) stooges) ; I'm curious why this is nil instead of false |
| 16:24 | piranha | dnolen: or to put it other way: can I get difference of my state between render calls? I'm trying to integrate with an existing library and I need to remove/add things by hand |
| 16:24 | piranha | depending on their presence in my state... |
| 16:24 | egghead | dnolen: I'm playing with using it for event handlers in om |
| 16:24 | dnolen | piranha: I'm pretty sure that isn't the case, but if you can create a minimal example that demonstrates this that would be helpful. |
| 16:24 | egghead | realizing i am using cljs core async, core.match and om ... THANKS |
| 16:25 | skyl | nvm, I googled it https://groups.google.com/forum/#!topic/clojure/JHGozQzOwFQ .. |
| 16:25 | piranha | ok, not today then :) time to sleep already, just thought that could be a small misunderstanding of the code :) |
| 16:25 | piranha | egghead: how do you use it? :) |
| 16:26 | dnolen | piranha: if you look at the Om source I just take nextProps from React and pass it on |
| 16:26 | dnolen | piranha: not saying there isn't a bug of course |
| 16:27 | piranha | dnolen: yeah that's what I saw, so I'm quite confused right now as you can imagine :) |
| 16:27 | piranha | sure, I'll try to replicate that in a smaller project tomorrow |
| 16:27 | egghead | piranha: nothing special on the cljs side yet re: core.match, just using it as a fancy condp = |
| 16:28 | egghead | om took me a while to wrap my head around but it's really cool once it clicks |
| 16:28 | piranha | it is :) |
| 16:28 | benmoss | dnolen: figured it out, it was coming from using om/read still. didn't read your changelog announcement closely enough, and your todo-mvc example still uses it |
| 16:29 | piranha | to be honest that's mostly react being cool though :) |
| 16:29 | dnolen | benmoss: I updated todo-mvc for 0.3.0 |
| 16:29 | egghead | hey dnolen fyi the current version of om pushed doesn't have IDeref |
| 16:29 | egghead | on MapCursor |
| 16:30 | egghead | master works wonderfully tho |
| 16:30 | benmoss | egghead: I am using it right now so I believe it does |
| 16:30 | dnolen | egghead: pretty sure that isn't true since I've tried it several times |
| 16:30 | egghead | :O |
| 16:30 | benmoss | you are probably having the same issue I had which was you have to delete the target directory |
| 16:30 | benmoss | or perhaps the compiled js directory, I'm actually not sure which one was the right thing |
| 16:30 | egghead | aah benmoss |
| 16:31 | egghead | ya lemme try a cljsbuild clean |
| 16:32 | egghead | yup, derpin on my end again |
| 16:33 | egghead | do core async chans get gc'd ? if I init them in an om component and then that component gets unmounted? |
| 16:35 | sobel | noob question: what is the var function? i don't follow what the Var object does |
| 16:36 | skyl | (def more-stooges (conj stooges "Shemp")) ; -> ("Shemp" "Moe" "Larry" "Curly") .. I'm using 1.5.1 and it seems that conj appends in this case rather than prepending as the tutorial says here .. did this change? |
| 16:37 | cark | stooges is a vector |
| 16:37 | cark | conj acts differently depending on the collection it works with |
| 16:38 | dissipate | cark, what happens if you conj a vector vs. a map? |
| 16:38 | cark | if you conj on a map, you get a map, that's not specifically ordered |
| 16:38 | cark | conjing on a vector adds to the end, on a list to the begining |
| 16:39 | dissipate | cark, BTW, have you ever run into performance issues with Clojure's built in data structures? |
| 16:40 | cark | i wouldn't mlake a game with clojure, but it's fast enough for anything business related |
| 16:40 | Wild_Cat | I'd probably write a game *server* in Clojure, though. |
| 16:40 | cark | Wild_Cat: yes |
| 16:40 | sobel | i would write a web game in clojurejs |
| 16:41 | dissipate | cark, why not? people are making games with Python (e.g. PyGame). clojure is higher performance than python, no? |
| 16:41 | dissipate | Wild_Cat, wouldn' t you write a game server in Go? |
| 16:41 | cark | dissipate: it is. We discussed that last week, it all depends on the type of game =) |
| 16:41 | tbaldridge | dissipate: it depends what you call a game. For example, EVE Online is mostly Python in the engine and client, but all the GFX is C++ |
| 16:42 | dissipate | tbaldridge, sounds like Panda3D which has Python wrappers for the underlying C++ API. |
| 16:42 | egghead | anyone know how you'd test something like om? |
| 16:42 | tbaldridge | Even the, World of Warcraft uses Lua for tons of stuff, but none of it is engine related. |
| 16:42 | cark | i'm not holding my breath for waiting for the next clojure FPS =) |
| 16:42 | Wild_Cat | dissipate: because the JVM is a rock solid runtime with pretty much any lib I'd want to use, Clojure is a pleasure to write and Go's neat ideas have been ported to it as core.async. |
| 16:43 | Wild_Cat | also, no need to bother with cross-compilation and dependency management because Leiningen and Maven kick ass. |
| 16:43 | cark | go has some weirness to it too |
| 16:43 | dissipate | Wild_Cat, where does Haskell fit into all this? |
| 16:43 | cark | weirdness* |
| 16:43 | tbaldridge | dissipate: don't say the H word... |
| 16:43 | tbaldridge | :-P |
| 16:43 | Wild_Cat | (also, Clojure's emphasis on immutability is great) |
| 16:43 | dissipate | tbaldridge, sorry. :P |
| 16:44 | Wild_Cat | dissipate: the Haskell ecosystem is meh, and every time I've tried to use it I've found most documentation hard to read and the community far too deep into its own academic arse. |
| 16:44 | dissipate | Wild_Cat, well, Docker should be eliminating all that anyways. |
| 16:44 | sobel | Docker will eliminate what? |
| 16:44 | dissipate | sobel, dependency management. |
| 16:44 | tbaldridge | dissipate: for me, the big "win" for Clojure is immutability + being a dynamic lang. No other language has the correct combination of a fast JIT, GC, immutability and dynamic typing. |
| 16:44 | sobel | dissipate: wrong layer |
| 16:44 | Wild_Cat | (generalized abstract arrow combinator combinator transformer combinator meta-libraries) |
| 16:45 | dissipate | sobel, have you used docker? seems like a godsend for deployment. |
| 16:45 | sobel | dissipate: yes, Docker is my other new learning thread. it's pretty awesome. |
| 16:46 | Wild_Cat | dissipate: however, I still think Haskell's type system is second to none. |
| 16:46 | dissipate | sobel, the possibilities for deploying super lightweight linux desktop apps seems quite interesting |
| 16:46 | Wild_Cat | typeclasses are an awesome idea. |
| 16:46 | sobel | dissipate: but i'm not seeing that i would want to delegate jar/clojar management to Docker containers when i sorta consider that something that should be in the programmer's hands |
| 16:47 | Wild_Cat | sobel: tbh I doubt the JVM ecosystem is the one where stuff like Docker yields the highest gains, because dependency management in Java/Clojure is a solved problem, thanks to Maven/Lein. |
| 16:47 | Wild_Cat | now in *Python*, though... |
| 16:47 | sobel | dissipate: yeah, i have some plans for making a 2-4 layer set of host containers for our main app at work. layers to rope it dev/qa stuff. |
| 16:47 | dissipate | sobel, clojars could be docker images that spin up a service that you connect another container to. that way the author of the clojar can have their library run *as intended* in the environment they developed it in. |
| 16:48 | bbloom | Wild_Cat: "dependency management" and "solved" in the same sentence? lol yeah ok |
| 16:48 | sobel | i know there's a lot of ways to do it, i hadn't really applied a lot of time or thought to using Docker for java deployment yet. i'm real green at Docker but i have an instance running on my VM. |
| 16:48 | bbloom | Wild_Cat: the JVM is only marginally less bad than some other things |
| 16:49 | Wild_Cat | (Python packaging, distribution and deployment are a nightmare) |
| 16:49 | bbloom | dependency management is bad everywhere |
| 16:49 | sobel | bbloom: +1 |
| 16:49 | bbloom | here we use (inc name) :-) |
| 16:49 | dissipate | Wild_Cat, what is the equivalent to virtualenv for clojure? |
| 16:49 | sobel | let's not turn ideologue over dep management. it's a mundane and ugly task but it's gotta be done right |
| 16:49 | Wild_Cat | dissipate: intuitively I'd say lein uberjar. |
| 16:49 | tbaldridge | dissipate: it's not needed, as you can specify all that in a project.clj file |
| 16:50 | ivan | dependency management will be solved when you have some guarantee that the jars you're running have any correspondence to the source |
| 16:50 | Wild_Cat | but what tbaldridge said. |
| 16:50 | bbloom | sobel: the best/simpliest solution on the JVM, just as it is anywhere else on unix, is to put all dependencies in a directory and use CLASS_PATH or similar |
| 16:50 | bbloom | it's far from ideal & many better solutions are available, but it's predictable and trivially simple |
| 16:50 | sobel | bbloom: inorite? i am so not about system installations of jar libraries. that never made sense to me. |
| 16:51 | dissipate | bbloom, and what about non-java depdendencies, such as stuff you run from /usr/bin? |
| 16:51 | Wild_Cat | dissipate: the reason we need virtualenv in Python is twofold: 1. The default installation method for Python libs/programs is centralized/systemwide with no conflict resolution; 2. There is no default way to *uninstall* a Python lib/app |
| 16:51 | sobel | same with system tomcat instance. wtf? do deb package maintainers even...java? |
| 16:51 | cark | this docker thing is unix only =P |
| 16:51 | Wild_Cat | and 3. Python 2 has no stable ABI, meaning that dependencies with C extensions need to be recompiled when you upgrade your Python version. |
| 16:52 | sobel | cark: really new linux only, too |
| 16:52 | Wild_Cat | (of course it's supposed to be a solved problem in Python 3, but, y'know. Python 3.) |
| 16:52 | dissipate | cark, good luck porting Docker to proprietary OSes like Mac OS and Windows. |
| 16:52 | cark | ahwell it sucks then =) |
| 16:52 | sobel | I'm here because python is neat but not neat enough |
| 16:52 | sobel | I'm confident Docker has the attention of other OS makers |
| 16:52 | dissipate | cark, you realize that is a problem caused by the corporations developing those OSes, right? |
| 16:53 | Wild_Cat | oh, and just for the fun of it, 4. Python installation scripts are imperative Python programs, making it really hard to analyze how any of this works. |
| 16:53 | cark | i code my clojure stuff on windows, an deploy as is on solaris |
| 16:53 | sobel | It's a really smart step in virtualization |
| 16:53 | tbaldridge | I write my code on Irix and deploy to Windows 98 |
| 16:53 | sobel | cark: i do that too. i love jar portability. |
| 16:54 | cark | sobel : haha yes ; install instructions are "drop the jar somewhere, launch it" |
| 16:55 | dissipate | cark, and non-java deps? |
| 16:55 | sobel | so, i can make an executable clojar, right? :) |
| 16:55 | sobel | dissipate: bad style ;) |
| 16:55 | dissipate | sobel, /usr/bin stuff? |
| 16:56 | cark | dissipate: i'm half jocking, but it certainly is the instructions for upgrading |
| 16:56 | cark | kill java, replace jar, launch |
| 16:57 | dissipate | cark, you do realize there are non-java deps that have to be deployed in a lot of cases? |
| 16:58 | cark | yesss |
| 16:58 | dissipate | cark, so i don't see how jar files eliminate the need for a virtual environment or something like docker |
| 16:58 | cark | like postgres =( |
| 16:59 | cark | dissipate: since i can't use it on solaris, the need is completely eliminated |
| 16:59 | Wild_Cat | dissipate: an uberjar is a self-contained version of your app (including all its Java deps), meaning you don't need a virtual environment at all. |
| 16:59 | cark | now why the customer is using solaris, i really can't tell |
| 17:00 | Wild_Cat | as for non-Java deps... Yeah, that sucks. And it sucks even worse that a lot of those have to be deployed on different boxes entirely. |
| 17:01 | Wild_Cat | and it's often up to your devops guy to make that process simpler. |
| 17:01 | dissipate | Wild_Cat, sounds like a better way to go. :P |
| 17:01 | cark | right, if they want virtualisation, let them do it |
| 17:02 | dissipate | Wild_Cat, or if you have a good PaaS, it will do that for you from a config file. isn't this the age of NoOps? :P |
| 17:02 | Wild_Cat | dissipate: yeah, figures. ~The Clouuuuuuuuud!~ |
| 17:06 | dissipate | is there a clojure equivalent to capistrano or fabric? |
| 17:09 | sobel | dissipate: thing is, it depends on how much of that deployment is system/static and how much is subject to change in the hands of developers. there's a role-responsibility transition, going from dev to deploy |
| 17:10 | sobel | for example, i'll be really glad to have Docker containers ready to run my java apps: vm installed, native bits if any, whatever else i deem is part of the app container. then i'll stuff jars into that container. same container can host most any java (server) app. |
| 17:12 | bbloom | dissipate: pallet is probably the closest thing |
| 17:13 | dissipate | sobel, well, in theory you should have 1 container per app/database engine. docker reuses base layers of the images anyways, and the processes run on the host machine directly. |
| 17:14 | dissipate | the problem with docker right now is that i don't think it's fit for all use cases due to lack of other tools to manage the containers properly, and i'm not even sure if it's even stable yet. |
| 17:14 | sobel | dissipate: i know i'm butchering the specific terminology |
| 17:15 | sobel | i've seen a recipe for deploying a nodejs app straight to docker |
| 17:16 | dissipate | sobel, yep, there are tons of recipes for docker. a number of projects on github now have a docker file in the repo to build a docker image for the app. |
| 17:17 | dissipate | sobel, from an ops perspective though, managing all the containers could turn into a nightmare. you could have hundreds or thousands of containers running god knows where. there are management tools like Shipyard, but outside of a PaaS type setup, nothing that's automated. |
| 17:19 | technomancy | speaking of non-java deps, we could use some help from someone who uses native deps in leiningen to get them documented for the next release |
| 17:19 | technomancy | afaik none of the regular contributors use native deps, so while they technically work their use is not documented at all |
| 17:31 | alew | technomancy: how do native deps work? |
| 17:33 | sobel | i figure the same JNI policy applies to clojure as to java |
| 17:33 | sobel | which for my use, means there are none |
| 17:45 | kristof | Oh! Just had a thought |
| 17:45 | kristof | porting Clojure to SBCL. That could be interesting (and introduce tail call optimization) |
| 17:45 | kristof | And you'd get this lovely lisp clojure interop |
| 17:45 | kristof | ...and reader macros! But I digress. |
| 17:45 | technomancy | alew: specifically in Leiningen, it looks inside all the jars and extracts .so files, etc appropriate for the current platofrm/architecture into target/ and sets a specific native load path to match |
| 17:50 | AeroNotix | kristof: and what features of SBCL is there that Clojure doesn't really have? |
| 17:50 | AeroNotix | besides the obvious like CLOS and restarts |
| 17:51 | cark | AeroNotix: what does clojure really have besides macros and persistent data structures ? |
| 17:51 | cark | =P |
| 17:51 | AeroNotix | cark: concurrency primitives |
| 17:51 | cark | and that ! |
| 17:52 | AeroNotix | But with interopping with the JVM/CLR you get access to a wealth of standard library stuff, with SBCL... the standard library is pretty meh, open-source code is all over the shop and there's a very small number of people trying to fix that issue (Xach e.g.) |
| 17:52 | AeroNotix | QuickLisp came out 20 years too late |
| 17:52 | cark | AeroNotix: there's the tail call optimization |
| 17:52 | AeroNotix | cark: clojure has recur\ |
| 17:53 | cark | that's really a problem with clojure |
| 17:53 | cark | clojure is for tail recursion |
| 17:53 | cark | not general tail call |
| 17:53 | AeroNotix | FWIW, there's nothing about Common Lisp which states it must have TCO. |
| 17:53 | cark | nope but all implementations have it |
| 17:53 | AeroNotix | Wrong |
| 17:54 | AeroNotix | CLISP doesn't really have it |
| 17:54 | cark | those that i know about |
| 17:54 | cark | ah possible, never really used that one |
| 17:54 | AeroNotix | It's pretty popular |
| 17:54 | cark | i've been using mainly lispworks |
| 17:54 | AeroNotix | Why? |
| 17:54 | hyPiRion | I haven't actually found a place where it really is a problem, except for DFAs maybe. Perhaps I'm working on the right type of problems |
| 17:54 | clojurebot | Why is startup slow is busy compiling the `for` macroexpansion |
| 17:54 | devn | Am I missing something, or is this weird given the docstring? |
| 17:54 | devn | ,(with-meta {:x 1 :y 2} {:a 1}) |
| 17:54 | clojurebot | {:y 2, :x 1} |
| 17:54 | cark | AeroNotix: it's nice on windows |
| 17:54 | devn | bah, nevermind |
| 17:54 | AeroNotix | cark: lolwat |
| 17:55 | AeroNotix | Development on windows with a fringe language, do you hate yourself? |
| 17:55 | cark | AeroNotix: it served me well =) |
| 17:55 | cark | AeroNotix: and support was top notch |
| 17:55 | AeroNotix | I'm sure some people can make it sing |
| 17:55 | AeroNotix | I just feel dirty thinking about it :) |
| 17:56 | AeroNotix | cark: so aside from TCO what do you want by putting Clojure on SBCL |
| 17:56 | cark | i don't specially want it, but if you put aside every goodie, then there's no reason to ever target any platform |
| 17:57 | cark | i've been bitten with TCO while doing monad stuff in clojure |
| 17:57 | AeroNotix | I didn't put aside any goodie, CLOS is not a good reason to switch, really. |
| 17:57 | AeroNotix | cark: sounds like you were programming clojure wrong |
| 17:57 | cark | CLOS is fantastic =) |
| 17:57 | AeroNotix | Dunno if "monad support" is a big Clojure feature :) |
| 17:57 | cark | it isn't ...because of TCO |
| 17:58 | cark | but hey, i'm here, so yes i find clojure very nice =) |
| 17:59 | AeroNotix | Well, there is that guy on reddit |
| 17:59 | kristof | AeroNotix: A variety of things, many of which have just been stated. Reader macros, TCO, CLOS, MOP, restarts/handlers, and some nice special control operators that are in the CL standard |
| 17:59 | kristof | AeroNotix: But more importantly, I really like Common Lisp, and I really like Clojure. So: "why not both? :D" |
| 18:00 | AeroNotix | then go for it, I watch sbcl on github, it's pretty actively developed |
| 18:00 | cark | the loop macro (*hides*) |
| 18:00 | AeroNotix | cark: now you're just trolling |
| 18:00 | cark | hehe yes i must confess |
| 18:02 | AeroNotix | Not saying that `loop' isn't very useful |
| 18:02 | kristof | AeroNotix: SBCL itself, or a SBCLclj (made up the name)? |
| 18:02 | AeroNotix | kristof: SBCL itself |
| 18:02 | kristof | Ah, well, I'm already a regular user and I sometimes read Christophe's blog posts about computational adventures related to SBCL :) |
| 18:03 | cark | AeroNotix: wouldd you consider clojure to be a fringe language too ? |
| 18:03 | AeroNotix | cark: Not really |
| 18:03 | cark | i think not anymore |
| 18:03 | AeroNotix | cark: here in Krakow there are a lot of Clojure shops it seems |
| 18:03 | AeroNotix | We're an Erlang shop and we just started a portion of a new project in Clojure |
| 18:04 | AeroNotix | (primarily for JVM interop because reasons) |
| 18:06 | AeroNotix | and coming from Erlang clojure is *such* a breath of fresh-air |
| 18:06 | AeroNotix | the productivity boost the JVM libraries give is crazy |
| 18:06 | cark | the syntax of erlang is just terrible |
| 18:07 | pdurbin | AeroNotix: which libraries? |
| 18:07 | AeroNotix | cark: Lies. |
| 18:07 | cark | AeroNotix: who's trolling now ? |
| 18:07 | technomancy | it's no lisp, but it's nicer than C descendents |
| 18:08 | AeroNotix | cark: when you program Erlang for a while you start to see why it's the way it is. It has pattern matching built into the very core. You need to make syntactic allowances for that. |
| 18:08 | AeroNotix | And pattern matching is a great way to program. |
| 18:08 | AeroNotix | (Not played full with core.match, yet) |
| 18:08 | AeroNotix | pdurbin: the main one is Authorize.net's SDK which is why we chose Clojure for this project. |
| 18:09 | AeroNotix | I'll end up releasing a clojure wrapper for it eventually, but it's inside our codebase at the moment. Probably will do the same for the PayPal SDK later this year, too. |
| 18:11 | AeroNotix | pdurbin: indeed. |
| 18:11 | AeroNotix | pdurbin: we need to integrate with that. |
| 18:11 | AeroNotix | Terrible documentation, SOAP/xml interface, they provide a Java SDK. So we went with that |
| 18:11 | AeroNotix | the alternative is to somehow figure out their API from very poor docs and write soap calls in Erlang (not fun!) |
| 18:12 | pdurbin | AeroNotix: sounds like you're pretty happy with clojure's java interop then |
| 18:12 | AeroNotix | pdurbin: very much so |
| 18:12 | AeroNotix | it's been a lifesaver |
| 18:12 | AeroNotix | lein's very cool as well, compared to rebar it's on a whole different level |
| 18:13 | AeroNotix | e.g. rebar's so dumb that if a project's dependency changes location, it won't do anything / detect this, despite clearly having access to all pieces of information |
| 18:13 | AeroNotix | (rebar is unfortunately the de facto Erlang 'package manager', if you can call it that) |
| 18:14 | AeroNotix | I had so much fun this week |
| 18:16 | pdurbin | the groovy and scala interop with java I saw in a talk at java one kinda scared me. seemed brittle and weird: http://irclog.greptilian.com/javaee/2013-09-26#i_25930 ... "have to go to `ls` to figure out to use ScalaClass$.MODULE$.greet()" |
| 18:16 | pdurbin | but I don't really know what I'm talking about |
| 18:17 | AeroNotix | never looked at either in depth, Scala just seems like: |
| 18:17 | AeroNotix | "Let's put all our ideas into a hat, shake it up, take them all out and implement them in that order" |
| 18:19 | pdurbin | "If you like programming languages and food, here's the culinary equivalent of Scala" -- https://twitter.com/bos31337/status/425524860345778176 |
| 18:19 | gfredericks | trying to do your own OOP on top of java's is inevitably confusing |
| 18:19 | AeroNotix | pdurbin: :) |
| 18:28 | pdurbin | C++ is to C as Scala is to Java, right? a bridge... some familiar stuff, some new stuff (functional programming) |
| 18:28 | bbloom | pdurbin: that's how i see it |
| 18:29 | cark | i would argue that idomatic c++ is nothing like c |
| 18:29 | AeroNotix | Yeah, they're completely different languages. |
| 18:29 | bbloom | pdurbin: i dislike both raw java and raw C, but i much rather use them over scala and c++ for their respective use cases |
| 18:29 | AeroNotix | bbloom: +1 |
| 18:34 | gfredericks | pdurbin: nice analogy |
| 18:35 | gfredericks | (inc pdurbin) |
| 18:35 | lazybot | ⇒ 1 |
| 18:40 | dobry-den | http://clojure.org/agents says that observation of the state of an agent (deref) is always immediate since it demands no cooperation/coordination. Is that not that case for Atoms? |
| 18:44 | bbloom | dobry-den: it is the case for atoms. it only points it out to clarify against the fact that the agent is otherwise asynchronous |
| 18:47 | dobry-den | bbloom: thanks |
| 18:48 | dobry-den | also, is it correct that you should only contain the computation within a `swap!` that deals with the old value of the atom, and any other computation should happen outside of it? |
| 18:49 | bbloom | dobry-den: rather than answer yes/no, i'll say that the function given to swap! may be re-run several times if a faster swap! occurs while it's working |
| 18:51 | bbloom | dobry-den: if the nature of a compare-and-swap isn't second nature to you, then it's pretty likely that you're not coding something that is going to be crazy high volume contentious writes... so just focus on correctness, not performance |
| 18:52 | bbloom | dobry-den: with respect to correctness, anytime you see more than one @ you should be weary that they may be inconsistent in the face of concurrency (somebody writes between the reads) and you should prefer to move more logic inside the swap function |
| 18:52 | bbloom | dobry-den: does that help? |
| 18:54 | dobry-den | i see. basically, my case is that my use of noir.util.cache/cache! on my homepage is holding up everyone whenever it's invalidated (and someone makes it recalculate) |
| 18:54 | dobry-den | (https://github.com/noir-clojure/lib-noir/blob/master/src/noir/util/cache.clj#L30) |
| 18:55 | bbloom | dobry-den: without studying closely, i'd be concerned about that code. it really should only deref once |
| 18:56 | bbloom | dobry-den: ah ok and i see the problem you're talking abouyt |
| 18:56 | bbloom | dobry-den: seems like it renders stuff inside the swap function |
| 18:56 | bbloom | probably a bad idea |
| 18:56 | dobry-den | (cache! "stats/post-count" (db/get-total-post-count)) |
| 18:56 | dobry-den | seems like that holds everyone up when it's invalidated |
| 18:56 | bbloom | yeah |
| 18:57 | bbloom | what it should be doing is swap!-ing in a flag that says it's pending & then send that work to a queue & then block on a delay for the result |
| 18:57 | bbloom | if other threads ask for the same id, they will see a pending flag & then get the same delay object |
| 18:57 | bbloom | when the work is finished, all the delays will be released |
| 18:58 | bbloom | that prevents duplicate work and also does minimal work inside the swap |
| 18:58 | bbloom | dobry-den: does that make sense? |
| 18:59 | dobry-den | yeah. it seems that for such a simple cache (like displaying total post count), you want users to just deref something without doing any logic, and rather do the swap! in a background thread. like something that runs every 10 seconds. |
| 19:02 | dobry-den | even a (go-loop [] (<! (timeout 10000)) (swap! cache <recalculate>) (recur))) |
| 19:03 | gfredericks | huh...core.async as just a scheduler? |
| 19:03 | warz | is there a clojure socket library, or do i just use java interop? |
| 19:04 | dobry-den | warz: Sockets with java is great |
| 19:07 | dobry-den | gfredericks: i'm so naive here but it's what i have come up with so far for such a trivial thing. (alts! [invalidator (timeout 10000)] ...) would be the logic for (recalc every 10 seconds unless you manually invalidate it). |
| 19:08 | gfredericks | dobry-den: seems legit |
| 19:09 | gfredericks | I just realized I'm using core.async in production o_O |
| 19:09 | gfredericks | (the weird part being that I only just now realized it) |
| 19:10 | dobry-den | i considered http://clojurequartz.info/ but it was heavier than what i needed. and the only way i could think of doing it would be to hit an http endpoint like "/flush-cache" |
| 19:11 | pdurbin | cark: your point about idiomatic c++ is well taken |
| 19:19 | pandeiro | is there a way to exclude files in cljsbuild? |
| 19:19 | rtyer | Could someone help me wrap my head around a problem parsing xml into a usable map? I'm using clojure.xml/parse with the goodreads api and have a very nested structure (maps and vectors) of :tag/:content. I'd like to transform it so that I have a map with a key of every :tag value and a value of every :content value. |
| 19:19 | rtyer | fairly new to clojure so not exactly where to start looking on how to transform this |
| 19:20 | pandeiro | i want to keep my *_spec.cljs files right next to my actual cljs, but they cause runtime errors if included in the app's output b/c of jasmine stuff |
| 19:29 | reytt | Think I may have found the answer to my question with org.clojure/data.zip. |
| 19:54 | _eric | what is the idiomatic way to iterate over a sequence when I don't care about the result? |
| 19:54 | _eric | (map) seems excessive |
| 19:54 | _eric | (doseq)? |
| 19:56 | S11001001 | _eric: dorun |
| 19:59 | _eric | I don't think I'm asking the question very well. I guess I want to run some code based on each of the things in the seq |
| 19:59 | _eric | like Enumerable#each in ruby |
| 20:01 | ivan | doseq then |
| 20:01 | rplaca | _eric: if you don't care about the result, dorun is what you want |
| 20:02 | rplaca | or doseq to specifically enumerate elements of the seq |
| 20:03 | _eric | it seems like using (for) here is not the right thing to be calling: https://github.com/papertrail/slack-hooks/blob/master/src/slack_hooks/service/mandrill.clj#L53-L57 |
| 20:03 | rplaca | _eric: I said that badly: I think doseq is what you want |
| 20:05 | rplaca | _eric: yeah, that "for" is lazy *and* it retains all the results |
| 20:06 | _eric | hah |
| 20:06 | rplaca | however, that may not matter because the prn will force evaluation (and why do you say you don't care about the result if you're printing it?) |
| 20:07 | _eric | I believe the (prn) was added to figure out why the (for) wasn't doing what was expected |
| 20:07 | _eric | and I believe the thing that wasn't expected was that the (for) was lazy |
| 20:07 | _eric | (lols all around) |
| 20:07 | rplaca | ah-ha. when laziness is the problem, printing can confuse the issue (by forcing evaluation that was otherwise never forced) |
| 20:07 | _eric | does this (for) make sense over being a (map)? |
| 20:07 | _eric | https://github.com/papertrail/slack-hooks/blob/master/src/slack_hooks/service/mandrill.clj#L33-L42 |
| 20:08 | rplaca | for and map are really two ways of saying the same thing |
| 20:08 | _eric | (I'm asking as for as what someone experienced would generally do in that situation) |
| 20:09 | bitwalker | The semantics are usually slightly different though, for consuming a collection versus transforming elements of a collection |
| 20:09 | rplaca | except that map evaluates the collections "in parallel", that is (f (nth a 0) (nth b 0)), (f (nth a 1) (nth b 1)), etc |
| 20:10 | bitwalker | Good point |
| 20:10 | rplaca | and for uses its bindings combinatorically |
| 20:10 | _eric | so (map (fn [event] ...) my-seq) would be a better way to do it |
| 20:10 | rplaca | which to use is more a matter of taste in different situations, I would say |
| 20:11 | _eric | though in this case, neither are going to really hurt/help me |
| 20:11 | rplaca | _eric: the map would be the same in this case |
| 20:11 | _eric | okay |
| 20:11 | rplaca | I would say that the for is *usually* preferable in this case |
| 20:12 | rplaca | but really doseq is what you want :) |
| 20:12 | _eric | yeah, I'm going to fix the bottom use of for to use doseq |
| 20:12 | _eric | just trying to figure out if I should change the upper use of for to use map (or something else) |
| 20:13 | warz | why are there so few results for "clojure irc client" on google? thats like the hello world of the internet |
| 20:13 | rplaca | generally, when you want side effects, use doseq unless you have a compelling reason to build a lazy sequence (cause you want to use HOF operators or something) in which case force the sequence with dorun after you've created it |
| 20:14 | rplaca | _eric: the upper for looks good, but stylisticly, only use the "do" when you bundling multiple steps |
| 20:15 | _eric | I was going to ask if tho (do) was needed |
| 20:15 | _eric | it didn't seem like it was doing anything |
| 20:15 | andyf | _eric: I may be missing some of the comments already said, but if the goal of those lines is to iterate over some sequence and print something out for each one, 'format' doesn't do anything but create and return a string. Do you want something like (println (format ...)) there? |
| 20:15 | _eric | that :let notation feels strange to me |
| 20:15 | rplaca | nope. |
| 20:15 | _eric | (it doesn't feel nessesary) |
| 20:15 | _eric | andyf: nope, we're trying to format the string and then eventually send that over HTTP |
| 20:16 | rplaca | yeah, you can always just use (let [] ...) inside the for rather than using the :let |
| 20:16 | andyf | _eric: So you do want this function to return a sequence of strings? |
| 20:16 | _eric | andyf: correct |
| 20:16 | andyf | _eric: The do is unnecessary |
| 20:16 | _eric | rplaca: do people generally do one over the other? |
| 20:17 | _eric | (the :let vs (let)) |
| 20:17 | scape_ | _eric: the link to your code is 404 |
| 20:17 | andyf | _eric: Each of the things you name in the :let bindings is used only once, I think, so it is really a matter of style whether you want to give them explicit names, or just use those expressions once each |
| 20:17 | rplaca | I'm not sure there's a set style. With this many syms I might use (let ) myself |
| 20:17 | andyf | _eric: Also, are you familiar with using :keys to bind multiple keys of a map all at once? |
| 20:18 | rplaca | but it's totally a matter of taste |
| 20:18 | rplaca | _eric: +1 to what andyf said |
| 20:18 | _eric | andyf: yes, we've used it in other places: https://github.com/papertrail/slack-hooks/blob/master/src/slack_hooks/service/tender.clj#L58-L67 |
| 20:18 | andyf | _eric: For example, the last 3 lines of your :let bindings could be rewritten as {:keys [email sender subject]} message, then use email, sender, and subject in the body |
| 20:19 | rplaca | but again, matter of taste - both are very readable |
| 20:19 | _eric | the :keys stuff really weirds me out at this point |
| 20:19 | _eric | I need to get more comfortable with it |
| 20:19 | _eric | but I've felt like doing it explicitly looks more approachable to me |
| 20:20 | rplaca | _eric: you get used to it and it weirds you out not to have it in other languages |
| 20:20 | andyf | _eric: Understood. It can look a bit strange at first. |
| 20:20 | rplaca | but I think python has something like it now |
| 20:20 | _eric | this project is a sort of hack project for us to get used to clojure |
| 20:20 | rplaca | iirc |
| 20:20 | _eric | and learn what the idiomatic way to do things is |
| 20:21 | rplaca | _eric: fwiw various kinds of destructuring are very idiomatic in clojure |
| 20:21 | andyf | _eric: Peronsally for me, the thing that stands out as oddest about that function is the unnecessary do. Everything else looks clear and understandable. |
| 20:21 | _eric | cool |
| 20:21 | _eric | removing that |
| 20:21 | _eric | https://github.com/papertrail/slack-hooks/pull/10/files |
| 20:22 | andyf | _eric: Did you want to return a sequence of strings, or the concatenation of all of them? |
| 20:22 | _eric | return a sequence of trings |
| 20:22 | _eric | strings |
| 20:22 | rplaca | the nice thing about destructuring is that it clearing shows the relationship of where things come from |
| 20:22 | _eric | so each one gets reported separately |
| 20:22 | _eric | I think part of the reason for not using the destructuring here was to be able to name the things better |
| 20:22 | Bronsa | _eric: you could turn that whole for in (for [{:keys [msg event]} (json/read-str ..) :let [{:keys [email sender subject]} msg]] ..) |
| 20:22 | rplaca | s/clearing/clearly/ |
| 20:23 | _eric | :msg -> message, :email -> recipient |
| 20:23 | _eric | bronsa: I hadn't considered that I could use the destructuring in the first argument to for |
| 20:23 | _eric | that's neat |
| 20:23 | andyf | Bronsa: I think it was pretty quick to update Eastwood for latest t.a(.jvm) changes. Output from crucible is back to what it was before, since the only thing you changed that Eastwood depended upon was :tag-kind |
| 20:23 | rplaca | _eric: makes sense, esp. if you have no control of what the keys are because they come from somewhere else |
| 20:24 | _eric | so much amazingness |
| 20:24 | _eric | rplaca: exactly |
| 20:25 | Bronsa | andyf: good to hear. I think I'm going to cut a beta release in a couple of days once I get a bunch of fixes in. |
| 20:26 | Bronsa | _eric: you can use destructuring everywhere you are binding something |
| 20:26 | _eric | hurray for mind-expanding exercises |
| 20:26 | _eric | this sure is different than ruby :) |
| 20:26 | _eric | or java |
| 20:27 | scape_ | :) |
| 20:28 | _eric | thanks for the help, guys |
| 20:39 | Raynes | I think gf3 and I communicate exclusively through snapchats now. |
| 20:40 | hiredman | /win 23 |
| 20:41 | rgrinberg | is there a fundamental reason why clojurescript doesn't implment stm? |
| 20:41 | andyf | rgrinberg: No parallelism in JavaScript engines |
| 20:42 | andyf | At least that is what I suspect would be the fundamental reason. I didn't implement it. |
| 20:45 | rgrinberg | ghcjs supposedly supports it |
| 20:45 | aaronj1335 | rgrinberg i'm new to clojure... but pretty familiar w/ JS, so why would you want stm in JS when you've got persistent data structures? |
| 20:45 | dnolen | rgrinberg: that's because they reify the entire TRS system, which is a horrible idea IMO |
| 20:45 | dnolen | s/TRS/RTS |
| 20:45 | dnolen | rgrinberg: JS engines are single threaded there's no point in supporting STM |
| 20:46 | aaronj1335 | ^ makes sense from JS perspective |
| 20:46 | rgrinberg | dnolen: why is it such a bad idea? i've only heard that it compiles to really fat js |
| 20:47 | dnolen | rgrinberg: because it means that they need a custom schedular that yield to the browser |
| 20:47 | dnolen | rgrinberg: I don't know they can guarantee a good behavior given the browser doesn't provide sensible hooks for proper scheduling |
| 20:48 | dnolen | rgrinberg: GHCJS is working (may even be available) building w/o the RTS at all because it isn't a good idea |
| 20:48 | dnolen | working on |
| 20:51 | rgrinberg | from the ghcjs blog: "Keep in mind that long-running JavaScript computations (called through the FFI or directly outside of Haskell code) will block all Haskell threads" yeah that does seem a little janky |
| 20:52 | kristof | janky being, of course, a technical phrase used in many white papers |
| 20:53 | kristof | "In this paper, we measure the effective jankiness of certain language constructs in the context of delimited continuations." |
| 20:56 | TEttinger | kristof, and the scale is based on reaction gif memes |
| 20:56 | devn | reduce-kv instead of, or in combination with persistent!/transient, reducers |
| 20:56 | devn | so much to think about |
| 20:58 | devn | (map (persistent! (reduce-kv (fn [x k v] (building-up-a-new-map)) (transient {}) {:a 1 :b 2}) [{:a 1 :b 2} {:c 3 :d 4}])) |
| 20:58 | devn | whoops |
| 20:58 | devn | (map #(persistent! (reduce-kv (fn [x k v] (building-up-a-new-map)) (transient {}) {:a 1 :b 2}) [{:a 1 :b 2} {:c 3 :d 4}])) |
| 21:30 | devn | hm, bummer |
| 21:30 | quizdr | hey fellas. can anyone explain what the runtime for something like LightTable is like, if it is basically clojurescript, which compiles to Javascript, then wouldn't the runtime be something like a browser? |
| 21:32 | akhudek | quizdr: I think it might be node-webkit. |
| 21:33 | kristof | ^ |
| 21:33 | quizdr | does that compile down into an actual executable, or is the runtime interpreted in real-time like javascript? |
| 21:33 | kristof | real time, I believe |
| 21:34 | kristof | You can edit the clojurescript configuration maps and it'll update your application |
| 21:34 | quizdr | intresting, ok |
| 22:07 | tutysara | ddellacosta: hi good afternoon |
| 22:07 | ddellacosta | tutysara: hi, saw your pull requests, will dig into them ASAP |
| 22:07 | ddellacosta | tutysara: thanks for all your efforts! |
| 22:08 | tutysara | ddellacosta: yw, thanks :) |
| 23:07 | mattmitchell | I have a few folks asking what the best clojure book is. Any recommendations? |
| 23:07 | Raynes | I'm fond of Chas Emerick's book. |
| 23:08 | Raynes | Clojure Programming |
| 23:08 | Raynes | The Joy of Clojure is a slightly more advanced book, but is also exceptional. |
| 23:10 | locks | JoC requires some fortitude, given the quite brisk pace |
| 23:10 | locks | but it pays off |
| 23:11 | mattmitchell | Great thanks. Do they both cover v 1.5? |
| 23:12 | mattmitchell | Or geez I can check on that :) |
| 23:12 | locks | WHAT'S INSIDE |
| 23:12 | locks | Covers Clojure 1.5 |
| 23:12 | locks | JoC 2ED ;) |
| 23:13 | mattmitchell | Awesome |
| 23:25 | dsrx | yep, Clojure Programming is a very good overview so far. Joy of Clojure was confusing when I read it the first time, I may go back and review it once i finish clojure programming |