#clojure log - Jan 26 2014

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0: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.

0:06 devn: this is also a little bit closer i guess...

0:06 ,(map second (filter #(= 'clojure.core/declare (when (coll? %) (first %))) (macroexpand-1 '(defrecord fooBaz [x y z]))))

0:06 clojurebot: (->fooBaz map->fooBaz)

0:06 devn: ,(resolve 'fooBar)

0:06 clojurebot: nil

0:09 devn: err

0:09 ,(defrecord fooBar [])

0:09 clojurebot: sandbox.fooBar

0:09 devn: ,(ns-resolve *ns* 'fooBar)

0:09 clojurebot: sandbox.fooBar

0:12 cark: ,(def test "hello")

0:12 clojurebot: #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>

0:12 cark: hum

0:12 clojurebot shouldn't let you define records i think

0:13 ,(->fooBat)

0:13 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ->fooBat in this context, compiling:(NO_SOURCE_PATH:0:0)>

0:13 cark: ,(->fooBar)

0:13 clojurebot: #sandbox.fooBar{}

0:13 devn: why not?

0:14 cark: you can polute the namespace, maybe dos it by defining many record types

0:14 devn: it does it in a sandbox

0:14 cark: right but the sandbox is still there isn't it

0:14 devn: for now

0:15 i think it gets cleaned up regularly

0:15 cark: you could write a script to make it go out of memory, and maybe crash

0:15 then why not let me def a var ?

0:15 same problem

0:16 devn: ,(let [shadow 1] (+ shadow 1))

0:16 clojurebot: 2

0:16 devn: ,(let [shadow "shadow"] (str shadow " puppets"))

0:16 clojurebot: "shadow puppets"

0:17 devn: maybe he runs it in an env that makes that not matter

0:18 oracle_: How to understand the: (map #(%1 %2) (cycle [inc identity]) [1 2 3 4 5 6 7 8 9 10])?

0:18 cark: he can't be "out of memory" proof

0:18 oracle_: what's the meaning of "(cycle [inc identity])"?

0:18 cark: or i want his box

0:19 oracle_: it's an infinite list : '( in identity inc identity ....)

0:19 devn: cark: im saying that maybe it (the vm/machine/whatever) just gets axed if it lives beyond its means

0:19 cark: oracle_: it's an infinite list : '(inc identity inc identity ....)

0:19 dissipate: clojurebridge is just for women? wtf

0:19 that's ridiculous

0:19 devn: is it really?

0:20 dissipate: devn, as a man, why can't i get free workshops? :(

0:20 devn: idk, you can if you're in my town

0:20 i dont know where you read that

0:20 dissipate: devn, which town?

0:20 devn: Madison, WI

0:21 dissipate: my suggestion is to not read the "for women" part too seriously

0: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> ......"

0:21 devn: just show up

0:22 cark: oracle_: look a this :

0:22 devn: inc is a function

0:22 cark: ,(take 10 (cycle [1 2]))

0:22 clojurebot: (1 2 1 2 1 ...)

0:22 devn: identity is a function

0:22 ,identity

0:22 clojurebot: #<core$identity clojure.core$identity@fbbe3f>

0:22 devn: ,inc

0:22 clojurebot: #<core$inc clojure.core$inc@1d1fda>

0:22 devn: ,(take 4 (cycle [inc identity]))

0: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>)

0:23 devn: ,(take 4 (cycle ['inc 'identity]))

0:23 clojurebot: (inc identity inc identity)

0:23 devn: ,(take 4 (cycle '(inc identity))

0:23 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

0:24 cark: it's pretty hard at first to see functions used as common data, stored in lists and whatnot

0:24 devn: ,(take 4 (cycle '(inc identity)))

0:24 clojurebot: (inc identity inc identity)

0:24 TEttinger: ztellman, those google ads were brilliant

0:24 jack_rabbit: ,(doall (range))

0:24 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

0:24 ztellman: TEttinger: ha, thanks

0:24 devn: jack_rabbit: dont break the bot :(

0:24 jack_rabbit: devn, He can survive it. :)

0:24 devn: (inc ztellman)

0:24 lazybot: ⇒ 8

0:24 cark: it's the "kill clojurebot" night

0:24 TEttinger: (inc ztellman)

0:24 lazybot: ⇒ 9

0:24 devn: cark: id like to see you try

0:24 quizdr: (inc clojurebot)

0:24 lazybot: ⇒ 33

0:25 devn: ive run a couple millions sexps in a sandbox from this channel

0:25 and had no issues

0:25 cark: devn : i don't want to write that script we talked about, but you may do it =P

0:25 devn: million*

0:25 TEttinger: also, ztellman have you considered a counterpart to primitive-math that provides primitive-coerced math ops?

0:25 devn: cark: my guess is you couldn't actually DDoS him with it

0:25 err DoS

0:25 cark: devn : got to try it to be sure

0:25 devn: whichever worked i guess

0:26 ztellman: TEttinger: can you expand on that? I'm not sure what you mean

0: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

0: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

0:27 I don't know if there's a faster way

0:28 cark: dsrx: there is an annoying phenomenon with printing out of the main thread and nrepl

0:28 ztellman: TEttinger: coercion at the point of the arithmetic call isn't necessarily the right thing to do

0:28 ideally you change something upstream, so it's not boxing at all

0:28 cark: dsrx: sometimes work and sometimes doesn't

0:28 devn: cark: im tempted

0:28 dsrx: cark: ah, I see

0:28 devn: im afraid of hiredman, but i feel like he probably took care of this scenario

0:29 TEttinger: I think I was using type hints incorrectly on my functions that returned numbers

0:29 devn: shall we try it?

0:29 dsrx: cark: well, I guess i can always swap messages into an atom and read them that way :P

0:29 devn: ,(doseq [x (repeatedly 100000 #((comp symbol str) (java.util.UUID/randomUUID)))] (eval `(defrecord ~x [])))

0:29 clojurebot: Execution Timed Out

0:29 TEttinger: ha!

0:29 dsrx: ,(launch-missiles)

0:29 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: launch-missiles in this context, compiling:(NO_SOURCE_PATH:0:0)>

0: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

0:30 devn: cark: toldyaso

0:30 ztellman: also, it's not clear at compile time whether it should be integer or floating point arithmetic

0:30 cark: devn make it smaller and do it again and again =)

0:30 ztellman: you'd have to do that at runtime, which is effectively what Clojure already doe

0:30 does*

0:31 devn: cark: your turn. i created the PoC, my work here is done. :)

0:31 cark: devn : i'm a pacifist at heart, let the poor clojurebot live

0:31 TEttinger: ztellman, that's why I chose a different fn name

0:31 cark: ~botsnack

0:31 clojurebot: Thanks! Can I have chocolate next time

0:31 ztellman: it's a valid approach in some cases, but not all

0:32 devn: Do you guys know of any interesting ways to capture ->fooBar and map->fooBar when (defrecord fooBar []) is defined?

0:32 ztellman: in a lot of cases it would just be papering over the underlying issues

0:32 devn: capture how?

0:33 or rather, in what sense?

0:33 devn: that's the question, i suppose. kovas posted about not being able to programatically find map->fooBar when given fooBar.

0:33 without string munging, that is

0:34 ztellman: string munging is valid

0:34 devn: ,(map second (filter #(= 'clojure.core/declare (when (coll? %) (first %))) (macroexpand-1 '(defrecord fooBaz [x y z]))))

0:34 clojurebot: (->fooBaz map->fooBaz)

0:34 ztellman: and the prize for most fragile solution goes to...

0:34 devn: that was my thought, but yeah, i suppose munging is just fine

0:35 hahaha

0:35 ztellman: *flick*

0:35 there are 100 ways to find it

0:35 i was just curious what clever sorts of things people would come up with

0: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)

0:36 devn: joshuafcole: #'clojure.core/satisfies?

0:36 joshuafcole: I'm hoping for something core (such that it would be applicable to cljs)

0:36 Oh, awesome! I'll check it out

0:36 thanks

0:37 devn: joshuafcole: there's also extends? and implements?

0:39 ztellman: thanks for collection-check

0:39 ztellman: devn: oh, you used it?

0:39 what for?

0:42 maravillas: dsrx: you're using cider/nrepl? have you looked for your output in *nrepl-server*?

0: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?

0: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

0:44 TEttinger: would (- width (long 2)) change it?

0:44 ztellman: TEttinger it might make more sense if you used no.disassemble to look at what that actually turns into

0:45 but in this case, 'width' isn't known to be a long

0:45 it might change later

0:45 so any code that references it gets the value out of the var, and it comes out as an Object

0:45 (- (long width) 2) fixes it

0:45 devn: ztellman: a CsvRecord type to allow for transformations while maintaining the header order

0:46 ztellman: devn: strongly encourage using potemkin unless you get hives thinking about that as a dependency

0:46 makes it infinitely easier to do map variants

0:46 devn: ztellman: yes, i've seen you messing with generating nonvariadic invocations and what-not

0:47 TEttinger: ztellman, so you said I should prefer... "ideally you change something upstream", but if def makes an Object...

0:47 devn: ztellman: potemkin.types is what i guess i'm referring to

0:48 TEttinger: would there be trouble if I wrapped the whole file in a toplevel let?

0:48 ztellman: TEttinger if it's really just a value, (def ^:const width 2) will just put '2' wherever you use the var

0:49 TEttinger: that's much better

0: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.

0: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

0:51 devn: ztellman: yeah, i am more in "fun time" mode right now with what im working on

0:51 but i still appreciate coll-check as a template for checking your own stuff works with clojure proper

0:52 ztellman: ha, yeah, I found issues with everything I had written beforehand

0:52 devn: that's just what simple-check does to you in general

0:52 dsrx: maravillas: aha! thank you

0:52 devn: i was messing with order on a set of fns that should have been idempotent over maps

0:52 dsrx: (inc maravillas)

0:52 lazybot: ⇒ 2

0:53 maravillas: welcome!

0:53 devn: aka #'this #'that #'another were all fns which operated on {...}

0:53 and no matter the order, they should all have produced Result: {...}

0:53 simple-check just made me sad

0:53 it's like lein-pedantic

0:53 prior to deps tree

0:53 it could just be incredibly sad to run sometimes

0:57 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.

0:58 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

1:00 ztellman: that's a big space to explore blind

1:01 I'd imagine you need some sort of hinting

1:01 devn: yeah, maybe. i think in general my mind is just wandering to: where all all the sub-repl envs?

1:01 s/all all/are all/

1:02 i want to do: (hmmmm '(my-fn 1))

1:03 and live in a separate development repl for a moment to analyze my code, profile it, etc.

1:03 sort of a dashboard for repl-based code analysis

1: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?

1:10 (assuming I have access to the project from github)

1:10 dsrx: egghead: clone the git repo, lein install

1:10 should work right?

1:10 egghead: probably...

1:11 noonian: yep

1:14 egghead: ah okay, I just had to do a cljsbuild clean too

1:14 thx dsrx noonian

1:21 dsrx: np

3:35 d11wtq: Can I get javadoc info from inside the REPL, without opening a browser?

3:38 xuser: d11wtq: with the lein repl you can

3:40 d11wtq: oh never mind, haven't tried it :D

3:41 though (javadoc) could do it

3:42 d11wtq: xuser: Yeah, #'javadoc tries to open your browser, which doesn't work in a headless environment (like SSH'd into a server)

4:32 deadghost: http://i.imgur.com/yUfD59c.png

4:32 just wanted to show off my crappy compojure/enlive app before going to bed

4:46 logic_prog: is there a way, in cljs, to register a function to be called when a channel is gc-ed ?

6:20 AeroNotix: ,(go (prn (+ 1 1)))

6:20 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: PermGen space>

6:23 cark: devn : see that ?

6:24 ,(+ 1 2)

6:24 clojurebot: 3

6:24 cark: mhh

6:24 ,(go 1)

6:24 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: go in this context, compiling:(NO_SOURCE_PATH:0:0)>

6:24 AeroNotix: ,(go (prn (+ 1 1)))

6:24 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: go in this context, compiling:(NO_SOURCE_PATH:0:0)>

6:24 AeroNotix: gremlins

6:25 cark: restarted maybe

6:26 a defracord would go to permgen wouldn't it ?

6:26 defrecord

6:26 ,(defrecor someRecord [])

6:26 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: defrecor in this context, compiling:(NO_SOURCE_PATH:0:0)>

6:26 cark: ,(defrecord someRecord [])

6:26 clojurebot: sandbox.someRecord

6:26 AeroNotix: I have 1.5.1 but I don't have clojure.core.async, do I need to download it separately?

6:27 (require '[clojure.core.async :as async :refer :all])

6:27 is how I'm trying to use it

6:27 cark: yes you need to add it to your project

6:27 AeroNotix: ok

8: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.

8:13 ^ actually, the result should be [:a 0 :b 1 2 3] since range starts from 0

8: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'))))))

8:24 clojurebot: #'sandbox/tm

8:24 wei__: here's what I got, maybe there's a better way using seq functions rather than recursion. https://www.refheap.com/27931

8:24 gfredericks: ,(tm [false true false true true true] (range) [:a :b :c :d :e :f :g])

8:24 clojurebot: (:a 0 :b 1 2 ...)

8:25 wei__: ah, lazy-seq. i always forget about that one

8:25 gfredericks: wei__: I think this is too weird for seq fns, but lazyseq+recursion is better than recur

8:26 wei__: i like seq functions because they're more clojurey, but is there an actual performance difference?

8:26 gfredericks: I'm not sure what you're comparing to what

8:26 wei__: your solution vs mine

8:27 gfredericks: I don't think there's an assymptotic difference. You can plug them into criterium to see

8:27 remembering that mine is lazy so you might want to doall or something

8:28 * gfredericks wanders off to change a diaper

8:28 wei__: laziness is a a nice feature

8:28 anyways thanks

8:28 (inc gfredericks)

8:28 lazybot: ⇒ 38

8:29 wei__: gluck with your kid

8:30 voldyman: hey guys, i am learning compojure my routes look like http://pastie.org/8668891 is this the right way?

8:58 gfredericks: voldyman: no

8:59 well depends on what the dummy handler stuff means

9:08 sobel: so, i'm selfteaching clojure with http://www.braveclojure.com/do-things/ but i am wondering if there are better tutorials

9:09 i'm also wondering just what the effort level is like for transfering my clojure knowledge to other lisps like Clozure

9:10 voldyman: sobel: try braveclojure its a good resource

9:10 sobel: voldyman: i do like it, and i'm getting through the syntax and types pretty easily

9:16 voldyman: gfredericks: the handler fn s take the values from params and would fetch data from the sql db

9:21 gfredericks: voldyman: you need to handle it inline or call your functions, not just mention them

9: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) ??

9:23 lazybot: voldyman: Uh, no. Why would you even ask?

9:23 voldyman: lazybot: because i am learning, and most sample code does it differently

9:23 dsrx: lol... rude, lazybot

9:23 gfredericks: voldyman: I'm surprised the functions are being called

9:24 sobel: is it normal to go code-blind with lisp really easily, coming from a java/C++ background?

9:25 hyPiRion: voldyman: lazybot is just a bot reacting to ?? and ???, just fyi. Right, lazybot???

9:25 lazybot: hyPiRion: Yes, 100% for sure.

9:25 sobel: i think my eyes are looking for ECMA style blocks and just not finding them

9: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.

9:26 sobel: voldyman: i'm familiar with the concept.. just trying to figure out how long i'll feel dyslexic reading functional code

9:28 voldyman: after reading just one tutorial i began to understand clojure, but with am totally lost after trying to read lots haskell

9:28 sobel: i'm trying to get my head around side-effect free programming

9:28 i hope/suspect that is the conceptual leap i need to make

9:37 jonathanj: i wonder if anyone else thinks it's weird that "(inc x)" mutates x :P

9:38 in the context of the bot, i mean

9:38 gfredericks: mutable numbers!

9:39 $google github flexnum

9:39 lazybot: [CSS3 Flexible Box Layout Explained | Smashing Coding] http://coding.smashingmagazine.com/2011/09/19/css3-flexible-box-layout-explained/

9:39 jonathanj: haha

9:39 gfredericks: $google github fredericksgary flexnum

9:40 bah

9:43 * gfredericks tries to imagine a PL with no values

9: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

9:48 gfredericks: clojure.org maybe? :)

9:48 RickInAtlanta: have you read the book "the joy of clojure"?

9:48 sobel: i've tried nada. that's why i'm asking around here.

9: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

9:49 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 :

9:49 I'm not doing static analysis (but might be forced to) should I use clojure.tools.analyzer ?

9: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

9: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

9:51 I don't know if it is exactly what you are looking for, but its a start

9:51 clojurebot: In Ordnung

9:55 ornicar: hello, I'm a scala dev giving clojure a try!

9:55 RickInAtlanta: hello

9:55 ornicar: I'm coding a project involving a HTTP/JSON client now

9:56 I read the great lein tutorial https://github.com/technomancy/leiningen/blob/stable/doc/TUTORIAL.md#readme and it leaves me with one question

9:56 how do you reload the code in lein, after you save your .clj file?

9:57 sobel: RickInAtlanta: thanks, i'm taking a look at it. jdbc is my first target, so that's not too far off

9:59 RickInAtlanta: sobel: this page on clojure.org walks through interop http://clojure.org/java_interop

9:59 Phonatacid: ornicar: (use 'my-project.core :reload)

9:59 ornicar: thanks, trying that now

9:59 Phonatacid: (besides : "mais ou et donc or ni car" ?)

10:00 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 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 I'm so excited to finally discover lisp :)

10:02 sobel: RickInAtlanta: thanks, both those refs are hitting the spot

10:03 it's gonna be weird getting used to chopping up java classpaths with /

10:03 (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 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 sobel it has its own idea about immutability, etc

10:52 sobel: interesting. good to know as a new-to-lisp person.

10:52 clojure is my first

10:52 borkdude: nice choice

10:54 RickInAtlanta: sobel there are a lot of syntax differences too.

10:55 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 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 however one of the things clojure does is it provides a standard way of doing things. particularly the sequence functions

11:00 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 everything i learned about sql lately has impressed on me the value of MVCC

11:05 no. wtf, must copy source array to get full immutability?

11:06 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 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 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 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 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 http://clojure.org/concurrent_programming

11:23 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 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 ,(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 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 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 my version is (loto (lcons [['g 'g] ['e w] [x y]] z))

11:45 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 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 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 I tried writing that with vectors, I am going to try rewriting with lcons

11:53 algernon: that line seems fine.

11:53 well, mostly, a few ' here and there.

11:53 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 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 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:07 * algernon nods

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 <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 ;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 How are they scheduled?

13:06 preemptively or co-operatively ?

13:06 gfredericks: on a thread pool

13:06 and the point is that lexically inside the go macro you are using things like >! and <!

13:06 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 all you're doing is taking a thread pool thread and keeping it

13:07 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 All the videos/talks lead me to believe it was semantically the same as Go's concurrency

13:08 ,(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 keyword is "visible"

13:10 AeroNotix: So, what are my options for user-space threading in Clojure?

13:10 pre-emptively scheduled

13:10 (last

13:10 (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 so the lib requires that to watch N files you need N threads polling

13:15 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 then those state machines are run on thread pools

13:20 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 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 Then (aaa (clojure.string/lower-case)) will expand to clojure.string/lower-case, which is what I want.

13:33 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 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 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 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 at least if you allow edge cases

13:52 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 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 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 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 Right, this works; thanks again.

14:01 * Cigitia is making a little µKanren clone

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 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 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 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 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 So, ok, I can rewrite all this to use purely channels with polling events. Thus allowing the go blocks to schedule

14:30 Yeah I didn't know that the go blocks *required* channel reads to schedule.

14:30 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 ?

14:36 dkinzer: gfredericks: sorry was trying out (in-ns) wihtout luck. It throws.

14:37 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 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 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 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 gfredericks++

14:55 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 i saw this thread but i double-checked my core.async and clojurescript versions and seem to both be latest

15:11 https://groups.google.com/forum/#!msg/clojurescript/P902i4FKA4w/3ndE9ax62_gJ

15:12 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 helped

15:13 benmoss: ill try that

15:13 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 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

15:17 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 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 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 dnolen : actually forgot the name... but anyways, it doesn't work with function maps

15:22 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 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 hrmm

15:52 cark: dnolen: one last question, oes ICloneable nee to implement deep cloning or shallow is good enough ?

15:52 need*

15:53 dnolen: cark: for Clojure data structures shallow cloning is deep cloning

15:53 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 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 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 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 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 ah seancorfield

16:19 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 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 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 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 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 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 on MapCursor

16:30 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 or perhaps the compiled js directory, I'm actually not sure which one was the right thing

16:30 egghead: aah benmoss

16:31 ya lemme try a cljsbuild clean

16:32 yup, derpin on my end again

16:33 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 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 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 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 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 :-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 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 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 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 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 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 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 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 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 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 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 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 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 which for my use, means there are none

17:45 kristof: Oh! Just had a thought

17:45 porting Clojure to SBCL. That could be interesting (and introduce tail call optimization)

17:45 And you'd get this lovely lisp clojure interop

17:45 ...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 besides the obvious like CLOS and restarts

17:51 cark: AeroNotix: what does clojure really have besides macros and persistent data structures ?

17:51 =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 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 clojure is for tail recursion

17:53 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 CLISP doesn't really have it

17:54 cark: those that i know about

17:54 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 ,(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 Development on windows with a fringe language, do you hate yourself?

17:55 cark: AeroNotix: it served me well =)

17:55 AeroNotix: and support was top notch

17:55 AeroNotix: I'm sure some people can make it sing

17:55 I just feel dirty thinking about it :)

17:56 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 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 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 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 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 We're an Erlang shop and we just started a portion of a new project in Clojure

18:04 (primarily for JVM interop because reasons)

18:06 and coming from Erlang clojure is *such* a breath of fresh-air

18:06 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 And pattern matching is a great way to program.

18:08 (Not played full with core.match, yet)

18:08 pdurbin: the main one is Authorize.net's SDK which is why we chose Clojure for this project.

18:09 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:10 * pdurbin looks at http://developer.authorize.net/integration/fifteenminutes/java/ ... ah... some payment system

18:11 AeroNotix: pdurbin: indeed.

18:11 pdurbin: we need to integrate with that.

18:11 Terrible documentation, SOAP/xml interface, they provide a Java SDK. So we went with that

18:11 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 it's been a lifesaver

18:12 lein's very cool as well, compared to rebar it's on a whole different level

18:13 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 (rebar is unfortunately the de facto Erlang 'package manager', if you can call it that)

18:14 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 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 "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 (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 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 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 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 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 (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 dobry-den: ah ok and i see the problem you're talking abouyt

18:56 dobry-den: seems like it renders stuff inside the swap function

18:56 probably a bad idea

18:56 dobry-den: (cache! "stats/post-count" (db/get-total-post-count))

18:56 seems like that holds everyone up when it's invalidated

18:56 bbloom: yeah

18:57 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 if other threads ask for the same id, they will see a pending flag & then get the same delay object

18:57 when the work is finished, all the delays will be released

18:58 that prevents duplicate work and also does minimal work inside the swap

18:58 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 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 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 I just realized I'm using core.async in production o_O

19:09 (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 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 (map) seems excessive

19:54 (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 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 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 _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 and I believe the thing that wasn't expected was that the (for) was lazy

20:07 (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 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 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 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 _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 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 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 (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 _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 I need to get more comfortable with it

20:19 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 removing that

20:21 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 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 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 bronsa: I hadn't considered that I could use the destructuring in the first argument to for

20:23 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 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 _eric: you can use destructuring everywhere you are binding something

20:26 _eric: hurray for mind-expanding exercises

20:26 this sure is different than ruby :)

20:26 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 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 s/TRS/RTS

20:45 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 rgrinberg: I don't know they can guarantee a good behavior given the browser doesn't provide sensible hooks for proper scheduling

20:48 rgrinberg: GHCJS is working (may even be available) building w/o the RTS at all because it isn't a good idea

20:48 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 "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 so much to think about

20:58 (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 whoops

20:58 (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 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 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 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 Clojure Programming

23:08 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 but it pays off

23:11 mattmitchell: Great thanks. Do they both cover v 1.5?

23:12 Or geez I can check on that :)

23:12 locks: WHAT'S INSIDE

23:12 Covers Clojure 1.5

23:12 JoC 2ED ;)

23:12 * locks http://www.manning.com/fogus2/

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

Logging service provided by n01se.net