#clojure log - Sep 18 2014

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

0:45 Rakko: I've been playing with Cider in Emacs. I definitely remember that a few days ago when I started a REPL in it, there was no warning about nREPL ops not supported. But now it's saying "WARNING: The following required nREPL ops are not supported: macroexpand-1 macroexpand-all". Are those features supposed to be supported?

0:45 (I'm 99% sure a few times I brought up REPLs using the same versions of Cider and nrepl-cider I didn't get that warning)

0:45 danielcompton: Is there a way to pretty prent exceptions in the REPL?

0:46 Jaood: Rakko: update cider

0:47 Rakko: cider-nrepl was probably updated by lein

0:47 Rakko: Jaood: I have the latest one from MELPA's normal repository (0.8.0alpha (package: 20140912.181))

0:47 Jaood: automagically

0:48 that's not the latest

0:48 Rakko: Hmm. Another question about lein: should the cider-nrepl plugin be specified as 0.8.0-snapshot, or 0.8.0-SNAPSHOT?

0:49 Oh, I see the updates now.

0:50 Upgrading it did take away the warnings.

0:52 Third question: why does cider-connect sometimes autodetect the port of a running REPL, but other times it doesn't?

2:21 paomian: hello

2:37 kyun: Could clojure have a gui lib, swing?

2:38 scottj: kyun: clojure can use swing, and there's a wrapper called seesaw

2:41 kyun: It seem like what I find, thank you.

2:42 ddellacosta: hrm, what's that function for swapping out key names again? forget

2:43 oh, it's in clojure.set

2:43 rename-keys

2:43 ,(rename-keys {:foo "foo"} {:foo :bar})

2:44 clojurebot: eval service is offline

2:44 ddellacosta: right, thank you so much hiredman

2:44 &(rename-keys {:foo "foo"} {:foo :bar})

2:44 lazybot: java.lang.RuntimeException: Unable to resolve symbol: rename-keys in this context

2:44 ddellacosta: &(clojure.set/rename-keys {:foo "foo"} {:foo :bar})

2:44 lazybot: ⇒ {:bar "foo"}

3:09 kenrestivo: ddellacosta: say, are you interested in patches for friend-oath-examples to deal with this? https://github.com/cemerick/friend/issues/117#issuecomment-53210040

3:10 ddellacosta: kenrestivo: most definitely, I've been busy as hell and slack on friend-oauth2 for now, but definitely think that stuff should get in there. And friend-oauth2 should definitely be extended to handle that in a non-hacky way, as much as possible.

3:11 kenrestivo: ok, i don't know how much time i'll have to do it, but i have to do it before april next year when google turns off their openid stuff

3:12 ddellacosta: kenrestivo: huh, I thought there was an ongoing conversation just about this somewhere in friend-oauth2, actually, but can't find it now...hrm

3:13 kenrestivo: if you find it, maybe reference it to that issue? or let me know here. i do have it working, just untested.

3:13 well, lightly-tested

3:13 ddellacosta: kenrestivo: oh yeah, there was this conversation, I think my thinking has shifted now that OpenID is a "real thing"

3:13 https://github.com/ddellacosta/friend-oauth2/issues/19

3:13 sure

3:15 kenrestivo: in any case, if you have a real solution go ahead and submit a pull request, if you'd like--or start an issue and we can talk through it there, what we think the best approach is. I'm definitely open to whatever

3:16 kenrestivo: ok, i just linked that issue together, just to leave breadcrumbs. i'll have a closer look at it, again, it has to happen before april anyway.

3:18 ddellacosta: cool, sounds good.

3:18 if it's just by April I'm sure we can come up with something solid by then, I should have more time myself.

3:26 Holy crap, there is this one key in a map that is giving me null when I try to get it out, but when I dump out the hash-map it's clearly got a non-nil value. WTF? Has anyone seen anything like this before?

3:27 giving me *nil* rather

3:34 thanks kenrestivo, I'll look at that and merge it in as soon as I've got time. May take a little while, but ping me if I disappear on you...

3:35 kenrestivo: np

4:02 ddellacosta: I am seriously going crazy here

4:02 wtf is this? https://gist.githubusercontent.com/ddellacosta/9a72a6ce52283ecbb1ae/raw/b503b25d28ccdf6293ac0913013492ee37573015/I%20am%20going%20insane

4:04 whoops, mistake.

4:04 https://gist.githubusercontent.com/ddellacosta/9a72a6ce52283ecbb1ae/raw/16ff3e9a3acafd467ac816c611caf734c01f4927/I%20am%20going%20insane

4:04 sm0ke: does the latest release of clojurescript only works with 1.6.0?

4:05 I keep getting. clojure.lang.ExceptionInfo: {:tag :cljs/analysis-error}

4:07 ddellacosta: sm0ke: https://groups.google.com/forum/#!topic/clojurescript/MEFJ5D7g8yM

4:08 sm0ke: yea sucks

4:08 what a leap

4:08 reminds me of scala and typesafe

4:09 hyPiRion: ddellacosta: you're going crazy, that's working for me

4:09 ddellacosta: hyPiRion: I know, and I just copied and pasted it in and it's working there too. WHAT is going on

4:10 hyPiRion: thanks for checking though. :-(

4:11 hyPiRion: ddellacosta: I guess a mean whitespace somewhere? :s

4:11 ddellacosta: hyPiRion: I don't know, it's clearly not showing up if I do pr-str though

4:12 hyPiRion: ,(let [  2 a  ] a)

4:12 clojurebot: 2

4:12 hyPiRion: I don't know

4:12 ddellacosta: hyPiRion: I'm importing from CSV -> hash-map, and it's just this one key (which of course, happens to be one I need) that is giving me this bizarre trouble

4:13 the only other time I've seen something like this is because of non-existent date hashing in ClojureScript

4:13 kenrestivo: fwiw, i lost several hours last night due to (for that should have been (doseq. worked in the repl, didn't work in production, should have known better.

4:14 hyPiRion: What clojure version are you running on? I think 1.5 had some exceptionally rare hash collisions for transients which was fixed in 1.6

4:14 ddellacosta: but this is all just strings, and it's all Clojure 1.6. Tried it in 1.7 and that was fine.

4:14 hyPiRion: yeah, I was wondering exactly that, but no. :-(

4:14 hyPiRion: maybe it was for 1.6

4:14 huh

4:14 ddellacosta: hyPiRion: er, sorry, I tried it in 1.7 and it's *the same*

4:14 d'oh

4:14 *not fine, that is

4:15 hyPiRion: alright, that's an amazing bug

4:15 Could you manage to pop up a minimal repro case?

4:15 kenrestivo: maybe, string equality test problem?

4:16 ddellacosta: hyPiRion: yeah, I've got to figure out how to reproduce it. Oh, the other lovely thing is--I tested this 'cause I saw it with the CLJS date/hash-map hashing bug--if I reduce the data I'm importing, it goes away. Like, chop off the last twenty columns of the csv, then it's fine.

4:16 hyPiRion: dunno, I'll give that a shot. This is freaking me out

4:16 kenrestivo: yeah, just dunno

4:17 hyPiRion: ddellacosta: oh boy. I wonder if you can use test.check to reduce the input somehow

4:17 ddellacosta: hyPiRion: sorry, I don't get what you mean--how would I do that w/test.check?

4:17 hyPiRion: (Not that it's very important really)

4:18 ddellacosta: I thought it generated data, not processed it? although been a while since I've touched it

4:18 hyPiRion: ddellacosta: Right. test.check has generators, and they can shrink the test case

4:19 ddellacosta: hyPiRion: ah, I see what you mean--so I'd have to model this data somehow first I guess? Well, it's starting out as just a csv file so I'm not sure it makes sense at the point it would interact with test.check.

4:19 hyPiRion: But it's probably too much work

4:19 yeah

4:19 ddellacosta: I mean, first I guess I have to nail down where this is happening. Seems like there is some weirdness going on in generation of the hash-map though

4:25 hahaha, I filter out the company specific data and the bug goes away. Awesome

4:25 hyPiRion: amazing

4:25 ddellacosta: I suppose that's a clue of some sort.

4:28 hyPiRion: ddellacosta: could you do (apply distinct? (map #(.hashCode %) my-set)) on the set with the bug?

4:29 ddellacosta: hyPiRion: yeah, let me give that a shot

4:30 hyPiRion: I guess that's probably not useful if (filter #(= s %) my-set) doesn't work, but at least worth a shot.

4:30 ddellacosta: true

4:30 hyPiRion: oh

4:30 ddellacosta: that is, the output was true

4:30 so, not a hash collision? huh

4:30 hyPiRion: Aw, was hoping it was false

4:30 Well, in theory.

4:31 ddellacosta: yeah, that would have been easier to understand. This is just bizarre

4:32 TEttinger: unless it's a string equality thing that distinct? is fooled by as well

4:33 kenrestivo: is it possible to make those all keywords instead of strings?

4:33 ddellacosta: TEttinger: well, .hashCode is going to dump out the hashcode for each set value, so I don't think it's in distinct?

4:33 kenrestivo: I actually started with keywords and just got rid of them when I was having the same problem

4:33 hyPiRion: TEttinger: yeah well, if we can't trust our strings then what do we do?

4:33 :p

4:34 TEttinger: is it possible the data itself is flawed?

4:34 hyPiRion: "Thousands of programmers evacuate the JVM when they realise when strings can't be properly compared"

4:34 TEttinger: like you are doing some processing on it to turn _ into -, and you have my-name and my_name in there

4:34 ddellacosta: TEttinger: I'm doing very little processing; just importing from CSV

4:34 TEttinger: splitting on a regex and then trimming (which I started doing *after* I saw this)

4:35 TEttinger: well you know the bad data is in company specific stuff -- how big is that?

4:35 ddellacosta: TEttinger: how big, in terms of the company-specific bits? I mean, that's going to change later on

4:35 I wonder if there are encoding issues here somehow

4:36 TEttinger: I mean just if you were going to go through and check it. encoding seems likely if strings are involved

4:36 kenrestivo: map them all to numbers, see what the char codes are?

4:36 ddellacosta: kenrestivo: interesting, let me try that.

4:36 TEttinger: yeah, could even be invisible chars that the map to numbers would check

4:37 clgv: ddellacosta: if encoding is involved two strings looking the same on output should have different hashcodes, which you can check

4:37 TEttinger: ,(map int "A lovely \u0006day wouldn'")

4:37 clojurebot: (65 32 108 111 118 ...)

4:37 TEttinger: ##(map int "A lovely \u0006day wouldn't you say?")

4:37 lazybot: ⇒ (65 32 108 111 118 101 108 121 32 6 100 97 121 32 119 111 117 108 100 110 39 116 32 121 111 117 32 115 97 121 63)

4:38 clgv: build a map for string to hashcode and see what the offending string hashes to

4:38 ddellacosta: clgv: right, can just call .hashCode huh

4:39 hyPiRion: something like (into {} (for [s my-set] [s (.hashCode s)]))

4:39 ddellacosta: yeah, I did map (juxt #(.hashCode %) identity) (into #{} (keys (first ed))))

4:40 er, (map ...)

4:40 hyPiRion: right

4:40 ddellacosta: although, not sure what I'm looking for. Now, should I get the same result from .hashCode for the same string, always?

4:40 hyPiRion: ddellacosta: yes

4:40 ddellacosta: okay, I can see a problem right here

4:41 &(.hashCode "PersonnelNbr")

4:41 lazybot: ⇒ 272039710

4:41 ddellacosta: right, that's what I get in my repl as well

4:41 kenrestivo: whyzat a problem?

4:41 ddellacosta: but, the output from the map above shows me for that string's entry: [-1523681379 "PersonnelNbr"]

4:42 ha, now I have an idea, what if I filter on that hashcode

4:42 hyPiRion: Aw dang. And here I was hoping I could fix a bug in the Clojure hashmap :(

4:42 ddellacosta: hahaha

4:42 well, I'm a bit relieved actually because that kind of a bug would be really, really bad

4:42 for us and everyone.

4:43 kenrestivo: why are they different? unicode?

4:43 clgv: but a string without any special signs hashing to two different values? are there such incompatible encodings? I thought ASCII is embedded everywhere the same

4:43 ddellacosta: clgv: yeah, I'm a bit confused by what is going on there

4:43 hyPiRion: (map int string)

4:43 clgv: or is there some magic in the string hashcode impl that adds the encoding to the hashcode?

4:43 hyPiRion: &(map int "PersonnelNbr") ; You should not get this

4:43 lazybot: ⇒ (80 101 114 115 111 110 110 101 108 78 98 114)

4:44 ddellacosta: hyPiRion: k, let me try that too

4:44 hyPiRion: clgv: oh wow. That would be... bad

4:44 clgv: but hey, you can check that by converting both to the same target encoding

4:44 ddellacosta: (filter #(= (.hashCode %) -1523681379) my-set) in my repl gives me the string: ("PersonnelNbr")

4:44 hyPiRion: clgv: I don't think that's reasonable to assume actually. Java HashMap would've experienced same problems if that were the case.

4:44 ddellacosta: and then applying hyPiRion's map

4:45 clgv: hyPiRion: ah ok, it does not?

4:45 ddellacosta: (map int (first (filter #(= (.hashCode %) -1523681379) my-set))

4:45 65279 80 101 114 115 111 110 110 101 108 78 98 114) !

4:45 er, w/parens at front

4:45 hyPiRion: clgv: I presume not? Java devs all over would cry

4:45 clgv: hyPiRion: I meant for the specific case here

4:45 ddellacosta: all the same but that 65279 at the beginning, must be some weird character artifact. Huh

4:46 clgv: invisible UTF-8 code?

4:46 ddellacosta: clgv: or something got chopped off/in half? but yeah

4:46 kenrestivo: ninja steganography

4:46 ddellacosta: ha

4:46 seriously, if you knew how to do this purposefully you could encode all kinds of random messages I guess

4:46 pull the first byte from every string and put 'em together

4:46 but I digress

4:47 hyPiRion: ,(Character/getName 65279)

4:47 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching method: getName, compiling:(NO_SOURCE_PATH:0:0)>

4:47 ddellacosta: "ZERO WIDTH NO-BREAK SPACE"

4:47 clgv: "BOM character" whatever that is?

4:47 ddellacosta: that sounds like the most useless character ever

4:47 kenrestivo: that is awesome

4:47 hyPiRion: Ah, the prediction

4:47 kenrestivo: a totally stealth character

4:47 ddellacosta: may as well name it "CHARACTER CREATED TO MESS WITH YOU, YES, YOU DAVE"

4:47 hyPiRion: 10:10| hyPiRion| ddellacosta: I guess a mean whitespace somewhere? :s

4:48 clgv: http://stackoverflow.com/questions/6538203/how-to-avoid-echoing-character-65279-in-php-this-question-also-relates-to-java

4:48 ddellacosta: hyPiRion: yeah, you nailed it. :-)

4:48 (inc hyPiRion)

4:48 lazybot: ⇒ 47

4:48 kenrestivo: who had stealth character in the pool?

4:48 ddellacosta: and then another for all the help!

4:48 and then another for all the help!

4:48 (inc hyPiRion)

4:48 lazybot: ⇒ 48

4:48 ddellacosta: whoops, dupe

4:48 TEttinger: that's incredible.

4:48 (inc ddellacosta)

4:48 lazybot: ⇒ 7

4:48 kenrestivo: how the hell did it get in there?

4:48 ddellacosta: TEttinger: :-)

4:48 hyPiRion: ddellacosta: Well I didn't really. :p I just guessed that it was the issue based on bad experience myself

4:49 ddellacosta: kenrestivo: must be something stupid I'm doing in the import.

4:49 actually, isn't there a CSV import lib for Clojure? I should be using that

4:49 hyPiRion: ddellacosta: yeah, data.csv I think

4:49 kenrestivo: yes there is, and that'd be wise.

4:49 clgv: https://github.com/tilo/smarter_csv/issues/27

4:49 TEttinger: I wrote one and didn't publish it.

4:49 ddellacosta: clgv: nice

4:49 TEttinger: it was uh not too hard

4:50 ddellacosta: TEttinger: yeah, that's the thing huh? My csv import is like five lines

4:50 but if there is a lib that prevents these issues specifically, I want to use it

4:50 hyPiRion: ah dang. http://dev.clojure.org/jira/browse/DCSV-7 seems to be unresolved

4:51 ddellacosta: hyPiRion: aha!

4:51 well, good to know I'm in good company at least

4:51 kenrestivo: ..." in Microsoft Land. " it figurs

4:51 ddellacosta: kenrestivo: seriously, I'll bet dollars to donuts the folks we got this from are on Windows

4:52 kenrestivo: \r\n

4:52 TEttinger: I think a regex replace that does all characters matching #"\p{Cf}|\p{Cc}" and replaces with nothing will work

4:52 ddellacosta: TEttinger: thanks, maybe I'll try that

4:52 TEttinger: \p{Cf} or \p{Format}: invisible formatting indicator.

4:52 hyPiRion: ddellacosta: oh dang, this is a serious issue in Clojure as well it seems

4:52 TEttinger: \p{Cc} or \p{Control}: an ASCII 0x00–0x1F or Latin-1 0x80–0x9F control character.

4:52 ddellacosta: hyPiRion: really? What else'd you find?

4:52 hyPiRion: ,"\ufeffPersonnelNbr"

4:52 clojurebot: "PersonnelNbr"

4:52 hyPiRion: ,(pr-str "\ufeffPersonnelNbr")

4:52 ddellacosta: ohhoho

4:52 clojurebot: "\"PersonnelNbr\""

4:53 kenrestivo: feff is unicode cruft IRC

4:53 ddellacosta: wow

4:53 kenrestivo: IIRC

4:53 hyPiRion: ,(let [x "\ufeffPersonnelNbr"] (= (read-string (pr-str x)) x))

4:53 clojurebot: true

4:53 hyPiRion: wat

4:53 ddellacosta: haha

4:53 hyPiRion: Oh, it's actually printed. Nevermind.

4:53 This is the words

4:53 *worst

4:54 ddellacosta: yeah, not happy about this little problem, but at least I can work around it

4:54 clgv: well pr-str and read-string prove consistent ,)

4:54 ddellacosta: you know, there's that saying, something like the only hard thing in programming is naming things and cache invalidation

4:54 hyPiRion: ,(let [x "\ufeffPersonnelNbr"] (= (.trim x) x))

4:54 clojurebot: true

4:54 clgv: you need a specialized trim^^

4:54 ddellacosta: I think encoding should be in there. I've had issues w/encoding throughout my career

4:54 right

4:55 hyPiRion: It's not even considered whitespace? This is amazing.

4:55 TEttinger: ,(let [x (clojure.string/replace "\ufeffPersonnelNbr" #"\p{Cf}|\p{Cc}" "")] (= (read-string (pr-str x)) x))

4:55 clojurebot: true

4:55 clgv: ddellacosta: http://stackoverflow.com/questions/6198986/how-can-i-replace-non-printable-unicode-characters-in-java

4:55 TEttinger: hm, that should be true

4:55 clgv: or what TEttinger said ;)

4:56 ,(let [x (clojure.string/replace "\ufeffPersonnelNbr" #"\p{Cf}|\p{Cc}" "")] (= (read-string (pr-str x)) "\ufeffPersonnelNbr"))

4:56 clojurebot: false

4:56 TEttinger: ,(let [y "\ufeffPersonnelNbr" x (clojure.string/replace y #"\p{Cf}|\p{Cc}" "")] (= (read-string (pr-str x)) x (read-string (pr-str y)) y))

4:56 clojurebot: false

4:57 kenrestivo: which of those is false tho

4:59 TEttinger: ,(let [y "\ufeffPersonnelNbr" x (clojure.string/replace y #"\p{Cf}|\p{Cc}" "")] (= x y))

4:59 clojurebot: false

5:00 TEttinger: ,(let [y "\ufeffPersonnelNbr" x (clojure.string/replace y #"\p{Cf}|\p{Cc}" "")] (= (read-string (pr-str x)) (read-string (pr-str y))))

5:00 clojurebot: false

5:00 borkdude: Is it possible to combine lein ring with lein gorilla?

5:01 can't find the option in lein gorilla to connect to an existing repl

5:01 ddellacosta: nice, it's working for me now. (:PersonnelNbr (first ed)) -> "00800113"

5:01 ヽ(;▽;)ノ

5:01 thanks to kenrestivo, TEttinger, clgv, and especially hyPiRion, you folks are awesome

5:01 kenrestivo: hyPiRion nailed it

5:01 ddellacosta: seriously

5:02 TEttinger: yep, hyPiRion wins with non-alphanumeric characters especially :)

5:02 (inc hyPiRion) ; another!

5:02 lazybot: ⇒ 49

5:03 kenrestivo: i'd love to find the preson who thought a non-printing zero-space invisible whitespace character that isn't even whitespace was a good idea

5:03 in the unicode spec

5:03 ddellacosta: kenrestivo: I bet they were on the Word project team at Microsoft

5:03 * ddellacosta shivers in remembrance of an older project

5:07 clgv: kenrestivo: they wanted some metadata ;)

5:08 kenrestivo: wait, now i'm confused. is that non-printing thing just FEFF, the BOM marker? in which case, its presence at least has some purpose.

5:08 clgv: yes it is. what purpose does it have?

5:09 kenrestivo: other than screwing up people's files, it seems to be there to indicate he byte order, hence its name.

5:09 clgv: ah that' what it abbreviates

5:09 kenrestivo: huh, it has an html entity too http://www.fileformat.info/info/unicode/char/feff/index.htm

5:09 clgv: but it does not make sense to add this to text files ^^

5:10 kenrestivo: anyway, i've run into this thing before, importing XML or something IIRC

5:11 hyPiRion: TEttinger: hahah, I wonder if I can use this in swearjure somehow

5:11 TEttinger: lol

5:12 hyPiRion: Alright, back to work before I actually start thinking about it

5:12 TEttinger: feff is alphanumeric, but the actual char is not...

5:21 justin_smith: ,(count "fefffeff")

5:21 clojurebot: 9

5:22 justin_smith: ,(count "")

5:22 clojurebot: 1

5:22 justin_smith: evil

5:22 ,(let [1])

5:22 clojurebot: #<CompilerException java.lang.IllegalArgumentException: let requires an even number of forms in binding vector in sandbox:, compiling:(NO_SOURCE_FILE:0:0)>

5:23 justin_smith: oh, clojure considers it whitespace

5:23 somewhat less evil

5:25 clgv: interesting.

5:27 justin_smith: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LispReader.java#L62

5:27 hyPiRion: Oh, while we're at it: https://www.refheap.com/35602

5:27 clgv: hyPiRion: will that erase my harddrive? :P

5:28 hyPiRion: clgv: no :p

5:29 But it will compile and work, because \u0022 is " (etc.), and it's presumably preprocessed before the java compiler actually tries to read the input

5:29 justin_smith: it's like the java version of trigraphs

5:37 TEttinger: ,(let [map (fn [f coll] (identity coll))] (map int "whee"))

5:37 clojurebot: (119 104 101 101)

5:37 TEttinger: justin_smith, \ufeff is a valid part of identifiers

5:38 the map in that let binding is named with one inside it :D

5:41 ,(let [map (fn [f coll] (identity coll))] (map char (map (fn [_] (.toString nil)) [66 67 68])))

5:41 clojurebot: (\B \C \D)

5:44 justin_smith: ,#{:a :a :a}

5:44 clojurebot: #{:a :a :a}

5:44 justin_smith: fun

5:44 and evil

5:59 borkdude: does slamhound also support clojurescript?

5:59 I guess not

6:00 I really need to clean up some namespace decl in cljs and hoped I could use smth like that

6:08 rstandy: hello clojurians

6:09 I'm tying to learn Om right now and I am really puzzled on Om cursors

6:11 how can be that you can change the app state atom when an Om component receives something like: (vals (:classes app))

6:11 ?

6:12 can someone help me understand? I'm aware of the fact that coursors maintain internally a path to get at the portion of the state that component manages, but what happens when a component receives a new value like in the example above?

6:16 clgv: rstandy: probably you'll have more success later today when all the US folks are around here

6:17 rstandy: clgv: ok, thanks for the suggestion :-)

6:25 ddellacosta: rstandy: also check out #clojurescript

6:26 rstandy: but I'm not sure exactly what you're asking--each component gets its own cursor, so

6:26 rstandy: er, just not sure exactly what you mean

6:31 rstandy: ddellacosta: thanks for pointing me to #clojurescript

6:32 ddellacosta: rstandy: sure thing.

6:34 rstandy: ddellacosta: anyway I was trying to uderstand how we can pass to a component a calculated value like in this expression: (om/build-all editable (vals (:classes app)))

6:35 ddellacosta: taken from the Om Basic Tutorial from David Nolen

6:35 ddellacosta: anyway I'll ask on #clojurescript also

6:35 ddellacosta: rstandy: ah, I see. Well, the basic idea is that when you apply some functions to a cursor, those will return a cursor as well. It's not everything, but that's baked into the cursor implementation.

6:36 rstandy: because a cursor is basically a protocol that is applied to standard Clojure data structures

6:38 for example, conj called on a MapCursor is going to return a MapCursor: https://github.com/swannodette/om/blob/master/src/om/core.cljs#L387

6:38 rstandy: sorry, I have that backwards: a cursor is a type that extends base Clojure protocols

6:38 rstandy: ddellacosta: wow! Impressive! so every function in the library operating on associative collections is supported?

6:38 ddellacosta: it wouldn't make sense the other way around. :-p

6:39 rstandy: ddellacosta: yeah right, I've got the point anyway

6:39 ddellacosta: rstandy: I don't know the answer to that, sorry

6:39 rstandy: ddellacosta: but now everything starts to make sense, many thanks for lighting me ;-)

6:39 ddellacosta: rstandy: but yeah, it's pretty powerful. At one point we had a SetCursor mostly working, although it had other issues so we dropped it...

6:39 rstandy: great. :-)

6:41 rstandy: ddellacosta: anyway, I must say that starting to learn Om after reading a Clojure book is like a course on applied magic :-)

6:42 ddellacosta: rstandy: haha, I know what you mean. Om really takes advantage of core Clojure concepts in some smart ways, that's definitely part of why it appeals to me.

6:45 rstandy: ddellacosta: yeah, I basically thought that following some David Nolen's projects would have made me a magician

6:45 ddellacosta: rstandy: heh. :-)

6:46 rstandy: ddellacosta: but I usually see madness waiting me on some corners :D

6:46 ddellacosta: rstandy: definitely taking some time to read through his source code is very enlightening. Reading Om's core.cljs has been instrumental in my understanding of it.

6:46 rstandy: well, there's always more to learn!

6:47 rstandy: ddellacosta: yeah great suggestion! I will read the code after finishing the tutorials

6:47 ddellacosta: again, many thanks for your enlightening answer

6:48 ddellacosta: rstandy: sure thing, glad I could help!

6:58 conorbev: Hi there

7:01 agarman: hi

7:05 conorbev: Sorry if this is a dumb question. I'm new to Clojure and using Cider in Emacs along with lein. M-x cider-jack-in works fine, but, I believe that it downloads the latest version of the cider-nrepl middleware each time that runs? (or at least it didn't seem to work when my wifi dropped!) Is there a way to make lein store the plugin away somewhere so that I do cider-jack-in without a network and upgrade the middleware myself wh

7:05 the cider Emacs package?

7:05 justin_smith: conorbev: are you using a snapshot version?

7:08 you can add :snapshot :never to the :repositories entry to prevent updates of snapshot versions https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L78

7:08 conorbev: justin_smith: yes, I am using from Melpa rather than Melpa Stable. I had some issues with stable version (this was a couple of months back when I last played with it. I can't remember for sure what the problems were).

7:09 justin_smith: but also, you can just not use SNAPSHOT dependencies - they are meant to be frequently updated

7:10 conorbev: justin_smith: Thanks, I will try that. Am I right in thinking the cider-nrepl middleware snapshot is going to be closely tied to a particular cider Emacs package version? So if I upgrade one I should update the other, but probably no point having one being newer than the other?

7:11 justin_smith: conorbev: the 0.7.0 release was intended to be stable, but there is little to no priority given to stability by the cider team

7:13 agarman: conorbev: as a cider user, let me pipe in. What justin_smith says about stability is spot on. I get a working version of emacs then only try out new versions in a sandbox.

7:14 justin_smith: "welcome to a confusing new language, first, before you can do anything else, play around with weird brittle configs that are usually broken"

7:14 clgv: when implementing a mouselistener I get "CompilerException java.lang.IllegalArgumentException: Mismatched return type: mouseClicked, expected: void, had: java.lang.Object"

7:14 what is going wrong?

7:15 I know that it does return void is the Clojure compiler malfunctioning here?

7:15 jazz2: hello

7:16 justin_smith: clgv: clojure can compile things that return void?

7:16 clgv: well reify should automatically match the signature of the interface - hence clojure must support that, otherwise reify is broken

7:17 conorbev: agarman: Thanks, and do you put :snapshot :never into your lein config? I was playing with clojure several weeks ago and went to try again just now. When I did M-x cider-jack-in it complained that macroexpand and macroexpand-1 wouldn't work unless I upgraded my Emacs cider package (this along with noticing it didn't work without wifi was what tipped me off that the underlying middleware must be changing). So it seems having

7:17 "working version depends not only on carefully upgrading Emacs package but not allowing the middleware to update automagically either

7:17 agarman: conorbev: I don't use melpa, I download cider from github

7:18 justin_smith: agarman: the issue here is that the clojure side middleware is auto-upgrading

7:18 as it is a snapshot version

7:18 and they released an incompatible version without changing the version string

7:19 clgv: justin_smith: interesting, removing the typehint for MouseEvent worked. so reify added implicit Object typehints because I specified the MouseEvent typehint...

7:19 justin_smith: clgv: under "Aliases" here I see that void is available for typehinting http://clojure.org/java_interop

7:19 TIL

7:20 clgv: that's kind of unexpected, but I guess you got it figured out?

7:21 clgv: justin_smith: yeah just removed the explicit MouseEvent typehitn since it is implicitely derived anyway

7:41 lvh: Hi! I'm getting the following exception when configuring a lein alias in project.clj; even though the same alias works fine in ~/.lein/profiles.clj: https://gist.github.com/lvh/46fce7e6eed268015a1e

7:42 (final exception: java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.String)

7:44 clgv: lvh: why do you have nested vectors there?

7:44 lvh: I didn't know that this nested notation is possible

7:45 humm seems valid according to the sample

7:48 lvh: clgv: I don't know, I picked it up from an article.

7:48 clgv: Seems to work in profiles.clj, though

7:49 Trying without the nested vecs

7:49 Yeah, same deal.

7:52 clgv: where is the project.clj?

7:52 lvh: interstingly, *none* of these aliases work, not even lein slamhound :)

7:53 clgv: Sorry, adding it to the gist now

7:53 try again: https://gist.github.com/lvh/46fce7e6eed268015a1e

7:54 clgv: do you have them set in both at the same time?

7:56 lvh: yes

7:56 is that not okay?

7:57 I would expect the local to override the global :)

8:00 clgv: welp, that is apparently the bug

8:01 clgv: lvh: leiningen has a profile merge logic. I suspected this might fail here

8:02 lvh: you have to explicitely use ^:replace to override some value

8:09 lvh: clgv: Cool, thanks! I'm trying to figure out how that works: https://github.com/technomancy/leiningen/blob/b497494b0445cb361381c71ff86517b4697a5419/leiningen-core/src/leiningen/core/project.clj#L432-L461

8:09 doesn't seem to handle :replace in meta

8:10 I guess that just merges?

8:10 clgv: you can use "lein pprint" so see the merged profile

8:11 lvh: ^:replace definitely works on top-level values, I use it for :jvm-args

8:11 lvh: clgv: Oh, I have no doubt that it works :)

8:12 clgv: ok maybe I misunderstood your previous comment

8:12 lvh: clgv: I'm just figuring out how leiningen does that :)

8:13 clgv: lvh: see `pick-prioritized`

8:13 lvh: 'pprint' is not a task. See 'lein help'.

8:13 clgv: Thanks!

8:16 Also, clojure.org https keeps showing me wikispaces.com certs; where do I file bug reports for that?

8:17 clgv: ok then pprint is still a plugin ;)

8:18 lvh: dont know what you mean

8:18 lvh: ah you mean when you access it via https?

8:18 lvh: yep

8:19 clgv: huh that's broken

8:19 humm mailing list?

8:20 lvh: on it :)

8:21 justin_smith: amalloy_: BTW, I figured out my issue - for lower primes the gap between even / odd streams is reasonable, but it grows linearly with the size of the numbers - so as the process runs more and more of the lazy seq is held onto as the odds trail behind the evens by larger and larger degree

8:22 *lower palindromes, not lower primes

8:29 lvh: clgv: Interestingly, lein show-profiles dev shows it correctly

8:30 clgv: lvh: probably because no merge happens if you only show a specific project

8:30 try "lein show-profiles user,dev"

8:32 lvh: lein cprint also shows both maps in different places

8:34 eskatrem: hey, yesterday I had some problem to update some fields in mongodb from clojure. I found the solution to my problem, not sure the guy who tried to help me is here. Anyway, my mistake was to search stuff with {:id "1"} instead of {:id 1}.

8:35 visof: hi

8:35 eskatrem: hi visof

8:35 visof: i have packaged my app as jar and tested it using java -jar app.jar and it's working very good, but when i package it as war and deploy in tomcat i got all routes 404

8:36 what is the best way to figure out it?

8:42 clgv: logging

8:43 justin_smith: visof: tomcat has extensive logs, have you checked those out at all?

8:45 dnolen_: just released ClojureScript 0.0-2341, quite a lot of changes around analysis, feedback welcome if you run into any issues

8:50 visof: justin_smith: yeah i got 404 not found for the routes

8:50 lvh: clgv: :aliases ^:replace {...} fixed it; thank you so much :)

8:51 justin_smith: visof: I mean, in the tomcat logs it should show which endpoints are being hit, any errors it may have, under which route it is mounting a particular war file...

8:55 jazz2: If you master the clojure ,what's you feel about scala program language

8:55 agarman: I spent 4 years programming Scala every day

8:55 I'd rather never write a line in that language ever again

8:56 jazz2: :agarman but now you are clojure channel ,why

8:56 agarman: I write Clojure for work.

8:57 and occasionally Java

8:57 and sometimes I have to support erlang code base

8:57 mavbozo: agarman: how you convince your boss to let you program in clojure?

8:58 agarman: mavbozo: they hired me to introduce the team to functional programming. the cto has a dev background; he wrote the erlang code we use in production.

9:01 mavbozo: there was little convincing needed. At the weather channel, we had to make the case for moving from C# -> F# and from Java -> Scala

9:02 jazz2: what is major difference between clojore and scala .

9:03 agarman: Scala is an okay language aside from a few really ugly warts: implicits, package objects (which make implicits transitive) and heavy reliance on concrete inheritance as an idiomatic design pattern

9:04 Clojure has some uglies too, but none cause anywhere near the confusion that those big three warts induce.

9:05 lvh: When I do lein deps :tree, the suggested exclusions always seem to suggest the lowest version. Is that intentional, or just a side effect of how they happened to be organized in my projects.clj?

9:08 jazz2: agarman: you say implicits is ugly ?

9:13 agarman: jazz2: let's not talk about #scala in #clojure

9:13 justin_smith: lvh: I think the assumption is that you would more likely want to exlude earlier versions vs. later ones

9:14 daniel___: agarman: what are clojures uglies

9:14 agarman: daniel___: as a lisp, it's confusing that () isn't falsy

9:16 hyPiRion: lvh: We peek into the dependencies and find the highest version of all dependencies. If the version used is lower, we suggest exclusions which cause the highest one to be picked

9:16 and yes, it has partly to do with ordering

9:21 lvh: hyPiRion: So, for example: https://gist.github.com/lvh/aaae39e7bb1170420705

9:21 Wouldn't [com.novemberain/welle "3.0.0" :exclusions [potemkin]] disable the 0.3.4 pulled in from welle?

9:25 hyPiRion: lvh: Whoops, inverse logic there. Yes – it suggests all the ones not used

9:25 borkdude: there is something with my subscription channel. It only receives a message once....

9:26 hyPiRion: Let me drag up the actual cheatsheet on that – My memory is apparently not 100% correct

9:26 lvh: https://github.com/technomancy/leiningen/issues/1337#issuecomment-25924936

9:27 lvh: hyPiRion: So what do I do to make it use the newer one, ideally in such a way that is future-proof? (I don't think lein-ancient checks deps transiently, but I could be mistaken)

9:27 hyPiRion: thanks!

9:28 hyPiRion: If lein-ancient doesn't check transient dependencies, then I'll add exclusions the opposite of what lein pedantic recommends

9:28 or, even better, I specify the dependency and its version in the :dependency vector

9:29 lvh: hyPiRion: okay, cool; so in this case I specify [potemkin 0.3.4] (or whatever I don't remmeber the version) in *my* project.clj's :dependencies?

9:29 Even though I don't actually depend on potemkin myself :)

9:29 hyPiRion: yes

9:40 foucist: so everyone here realizes that tests (TDD/BDD) are just a step away from some sort of constraint/logic programming right? so if we take something like tests or a better form of constraint-based DSL, and then hook it up with machine learning or evolutionary computation, it'll generate the solution to the problem given by the constraints

9:40 so any thoughts about how to approach this in clojure?

9:42 borkdude: tricky, I thought sub would return the channel to read from

9:43 I don't know what it is that it returns though, but you can read from it

9:47 it was not the solution for my problem however

9:48 hyPiRion: foucist: https://www.youtube.com/watch?v=5Q9x16uIsKA#t=1159

9:49 foucist: hyPiRion: would you use that for TDD though? :P

9:49 i probably want a hybrid spec/logic DSL

9:49 hyPiRion: foucist: I don't use TDD, but if I were to, I'd use test.check

9:50 Quickcheck sounds similar to what you want, although not exactly the smae

9:50 *same

9:51 foucist: not bad

10:11 TimMc: foucist: You would need to make sure to represent *all* the constraints, and that's very, very hard when you include things like run time and GC perf.

10:13 foucist: TimMc: well i'm really talking about something that generates a programmatic solution that can then be run from then on

10:14 and not sure if all constraints are necessary, could give it leeway to do whatever, all i'd really be checking for is input/output & no side effects..

10:16 clgv: foucist: there is PushGP whose current main implementation is in clojure

10:16 TimMc: In real code, heap allocation, GC pauses, and stack consumption have to be considered as side effects...

10:17 clgv: ah it's actually called Clojush https://github.com/lspector/Clojush

10:18 TimMc: You might say "nah, it's OK to have massive GC pauses on this batch job", and that's fine, but you have to at least answer taht question...

10:21 eristic: Hi everyone! I'm a Clojure/functional language n00b coming out of Ruby, and I'm looking for a list of essential reading material. Any suggestions?

10:21 borkdude: eristic Clojure Programming is nice

10:22 eristic there are a lot of good books now

10:24 mavbozo: for lightreading, you can start from clojure from the ground up by Aphyr http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome

10:24 eristic: I'm starting with Marick's Functional Programming for OO Programmers

10:24 sveri: Ok, a quick survey, which build server has the best clojure / leiningen support?

10:25 eristic: Thanks borkdude and mavbozo

10:25 mavbozo: eristic: I also found that doing 4clojure.com helps me understand quickly

10:25 sveri: pardon me, but what is "build server"?

10:26 sveri: mavbozo: jenkins is one, bamboo and some others, something that builds your artifact and deploys it somewhere

10:29 mavbozo: sveri: oh, that continuous integration thing

10:30 foucist: hmm, a grammar could be a good constraint-based DSL

10:30 mavbozo: sveri: circleci is quite good, plus it's cheaper than others

10:31 TimMc: eristic: A couple warnings: clojure.org has bad getting-started instructions (use leiningen!); clojuredocs.org is a couple versions out of date.

10:32 eristic: TimMc: Noted!

10:32 daniel___: eristic: i liked the clojure cookbook

10:34 mavbozo: eristic: and you can use http://grimoire.arrdem.com/ as your clojure cheatsheet. It's nicer than http://clojuredocs.org or http://clojure.org/cheatsheet

10:34 daniel___: its a more practical introduction, you can fill the rest in from other sources

10:50 stuartsierra: ,(sort [[1 2 3] [4 5]])

10:50 clojurebot: ([4 5] [1 2 3])

10:50 stuartsierra: Gets me every time.

10:51 TimMc: heh

10:54 clgv: are there known problems with canceling futures? I do (let [f (future ....), result (deref f timeout :timed-out)] (when (= result :timed-out) (future-cancel)) result)

10:54 but some threads seem to stay around and are not canceled

10:55 stuartsierra: The KVM offers no guarantees about the ability to destroy a thread.

10:55 *JVM

10:55 perplexa: stuartsierra: so it sorts by size?

10:55 or how does that happen?

10:55 stuartsierra: perplexa: size first, then by contents

10:55 perplexa: ,(sort [[1 2] [4 5]])

10:55 clojurebot: ([1 2] [4 5])

10:55 loliveira: Hi, I’m staring to use stuartsierra’s compoment library and I am dealing with a kind of leak. The system still has a reference to a subsystem after stop have been called. Could you please help me to point what I am doing wrong? https://www.refheap.com/90396

10:55 perplexa: cos that works ;x

10:55 stuartsierra: ye ok :)

10:55 lvh: Hm; why is (a/<!! (a/go (assert false))) ;; => nil? I was expecting that assertion error.

10:55 Not raised, but as avalue.

10:56 clgv: then it would be nice if the doc string of future-cancel mentions this fact

10:56 stuartsierra: loliveira: If you're implementing your own system records, you have to call `start-system` / `stop-system`.

10:57 In your implementations of start/stop.

10:57 But you probably don't need nested systems.

10:57 foucist: ,(sort [[1 2 3] [5 4]])

10:57 clojurebot: ([5 4] [1 2 3])

10:58 loliveira: stuartsierra: I’m not using nested systems. Am I?

10:58 stuartsierra: loliveira: Yes, you are.

10:58 Your `SuperSystem` record?

10:59 You haven't shown the `new-system` constructor, but you're calling it inside `system-map`

10:59 Also, `component` does not promise to dissoc dependencies on `stop`.

10:59 daniel___: ,(sort [[1 2 3 4 5 6] [1e5]])

10:59 clojurebot: ([100000.0] [1 2 3 4 5 ...])

11:00 loliveira: stuartsierra:(defn new-system [args]

11:00 (map->SuperSystem args))

11:00 stuartsierra: loliveira: OK, I was confused by the name 'SuperSystem'

11:02 loliveira: stuartsierra: SuperSystem is just a component. I agreed i choose a bad name.

11:02 stuartsierra: loliveira: Right, so 'Component' doesn't dissoc dependencies on `stop`.

11:03 See discussion at https://github.com/stuartsierra/component/issues/9

11:03 loliveira: stuartsierra: yes. It dissoc on (-> system :io ), but not on (-> system :app :io)

11:04 stuartsierra: loliveira: You did that, at line 17, `(dissoc component :io)`

11:07 loliveira: stuartsierra: yes, I did it, but I sttil have a reference to the io subsystem through (-> system :app :io). I was expecting the reference was removed after calling stop.

11:08 stuartsierra: loliveira: No, it doesn't do that.

11:09 loliveira: stuartsierra: I’ll read the link that you send me. Thank you for your help. It doesn’t do that, but shouldn’t do it? It seems natural.

11:09 stuartsierra: loliveira: there are reasons, discussed on Github

11:10 loliveira: stuartsierra: Ok, thank you again. Component is a great library. Thank you.

11:10 stuartsierra: you're welcome

11:23 seangrove: dnolen_: Does https://github.com/clojure/clojurescript/commit/877b1ab2e6bb1c09d1988348d6cb384f8ba16414 (CLJS-858) mean that if a function in another ns isn't defined, the compiler will give a warning now?

11:24 kyrre: I am experiencing some issues when trying to initialize a Java singleton class in clj: https://gist.github.com/kyrre/8caadbe2730642157326

11:26 boodle: trying to change a string from "om [clj js] testing" -> ["om" "[clj js]" "testing"]

11:26 regexps/split get me close but stuck on preserving the quoted "[]"

11:39 lvh: Does clojure.core.test have any utilities for skipping tests, or does that mean moving to midje?

11:40 clgv: lvh: aren't ther filter options via metadata? "lein help test" could help

11:40 lvh: there is for midje, I couldn't find anything about it for c.c.t; checking now :)

11:40 oh, hey, test-selectors!

11:40 clgv: ;)

11:41 lvh: thanks clgv!

11:41 clgv: you're welcome

11:45 borkdude: Why is my counter only inced once in this snippet? https://www.refheap.com/90399

11:48 lvh: (inc clgv)

11:48 lazybot: ⇒ 26

11:48 lvh: I think I owe you more than a few incs there, clgv

11:49 by the way, is there a way to :exclude in :require? I want to clojure.core.async :refer :all, but clojure.core.async has a thing called "reduce"; I'd much rather have the core reduce than c.a's reduce :/

11:54 clgv: lvh: lol no problem ;)

11:55 lvh: there is :rename

11:56 lvh: but yeah, there is also :exclude

11:57 lvh: clgv: I tried that, watched it fail, but apparently that's for a different reason... *tries*

11:57 clgv: lvh: should work though, cf https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4052

11:57 lvh: clgv: There's something weird going on; suddenly it can't find core.async anymore :/

11:58 clgv: doomsday is near...

11:58 ;)

12:07 lvh: Is it possible to write macros that use "<!" given that it wants to be used it a go block so badly?

12:08 I've got https://gist.github.com/lvh/0d7ddbd05196c777eb69

12:09 clgv: lvh: yeah, why not? as long as the macro expands within the go block

12:13 borkdude: help. http://stackoverflow.com/questions/25917557/core-async-pub-sub-in-om-clojurescript

12:14 lvh: Is there a way to "purge" namespaces when I start getting errors like "x already refers to this-specific-x in namespace..."?

12:14 Other than "restart the nrepl process" because that takes unacceptably long

12:14 maybe I should just buy a faster machine :)

12:14 clgv: manually `ns-unmap`

12:16 lvh: (dotimes [_ 10] (inc clgv))

12:16 no dice huh

12:21 clgv: 2d6

12:21 clojurebot: 9

12:21 clgv: this is a dice roll ^^ ;)

12:22 two to be exact...

12:22 lvh: Nice :)

12:22 So, I wrote some macros in terms of some other macros; are there ways to make this neater still? https://gist.github.com/lvh/0d7ddbd05196c777eb69

12:22 also has someone put that in a library? there's several blog posts and tutorial videos that mention that fn, it seems like it'd be useful to either have in clojure.core.async or at least in some lib

12:23 clgv: seems pretty concise

12:23 noonian: looks good to me, except i keep reading 'throwing-up' instead of 'throwing-op'

12:25 lvh: noonian: same here

12:57 kenrestivo: is doing lots of stuff inside of a let kind of smelly?

12:58 dnolen_: kenrestivo: just depends, in the past you often didn't have another option there are some neat macros for common cases now

12:59 kenrestivo: (let [foo <10 lines of code> bar <10 more lines of code> baz <10 more lines>] (something-simple! foo bar baz) foo) has a bit of an odor to me

13:00 hint: some of those 10 lines include calls to client/get

13:01 * kenrestivo rewrites

13:04 justin_smith: clgv: regarding cancelling, the doc string for future-cancel does say "if possible" - if your future code is a loop of some sort, add a check as to whether the current thread is cancelled, and exit the loop if it is

13:04 clgv: future-cancel will set that cancelled flag, you need to check for it and act on it though

13:05 danneu: i've changed up my development workflow so that i can now spam (start-server!) in my emacs buffer as i code. it reset!'s my `server` atom. but now none of the printlns within my handler show up anywhere.

13:05 what's the main culprit for this?

13:06 justin_smith: ,(.isInterrupted (Thread/currentThread)) ; clgv

13:06 clojurebot: false

13:07 clgv: justin_smith: well that's not possible without much effort.

13:08 justin_smith: OK, maybe it would be easier with a go block and a poison channel

13:08 clgv: I'd prefer that the jvm would just kill thread from the threadpool and start a new one

13:08 justin_smith: hell, I wish the jvm supported proper tail recursion

13:08 tail calls even, while we are at it

13:08 clgv: well can live without it

13:09 since the jvm supporting tail call optimization would have not much impact on the programmer since the hard part is to find the tail recursion which you have to do anyway

13:10 justin_smith: a compiler can trivially detect and optimize tail calls, if it knows what they are and has some mechanism for them

13:12 not just self calls mind you, but general calls from the tail position

13:18 noonian: proper tail calls would be amazing

13:22 CookedGryphon: I like that clojure makes you be explicit about tail calls, quite often, especially when learning I thought I was doing tail calls, only to find I wasn't

13:22 if I wasn't using the recur form, I would have carried on blissfully unaware until it exploded

13:23 it's doubly relevant when editing code and not realising that your innocuous log is actually breaking your tail call

13:29 noonian: CookedGryphon: but unfortunately you can't use recur to do mutual recursion, only self recursion, and trampoline adds more cognitive overhead for the programmer

13:33 clgv: justin_smith: but the compiler cant transform arbitrary recursion to tail-call recursions

13:33 justin_smith: sure

13:33 rweir: not with that attitude

13:33 justin_smith: no compiler can do that

13:34 clgv: justin_smith: so what exactly is the benefit you talk about?

13:34 justin_smith: automatic optimization of tail calls - not just self calls, but general tail calls

13:34 reduced stack usage, better performance

13:34 noonian: ^

13:34 clgv: ah you mean calls to other functions...

13:35 rweir: is it wise to have /some/ recursion magically use TCO and some not, with no indication in the source of which is which?

13:35 noonian: the indication is whether not the call is a tail call

13:35 rweir: hm, right

13:36 justin_smith: rweir: it isn't wise to count on it, but why object to getting it for free

13:51 PigDude: CookedGryphon: sounds like stockholm syndrome

13:52 CookedGryphon: being unaware of the difference between tail-recursive and non-tail-recursive code is a different matter than clojure requiring (recur) for TCO, the former is confusion, the latter a real limitation

13:53 amalloy: justin_smith: the argument is that if you get it for free you'll end up counting on it. then when you edit some tail-recursive code and accidentally make it not tail-recursive, the compiler won't tell you

13:53 * PigDude prefers functioanl languages w/ TCO

13:54 amalloy: and you aren't really checking for that, because you have lots of code that's not tail-recursive; it usually doesn't matter

13:55 noprompt: dnolen_: hey david, this backtick thing is a bit intimidating. how should i approach it?

13:56 dbasch: is this (if (> idx 9) 9 idx)) the same as (min 9 idx) or do I need coffee?

13:56 :P

13:56 amalloy: dbasch: looks like it to me

13:56 dbasch: (doing a code review)

13:56 noprompt: dnolen_: it seems like a reader problem.

13:56 justin_smith: dbasch: modulo the extra close paren

13:56 dnolen_: noprompt: yes it's a reader thing

13:57 noprompt: probably worth asking Bronsa about this too

13:59 noprompt: Bronsa: for context, the problem is with reading forms like `{:x 1} returning a form like (clojure.core/with-meta (clojure.core/apply clojure.core/hash-map ...)

14:01 Bronsa: this affects the cljs compiler resulting in meta leaking into the compiled source.

14:01 Bronsa: https://gist.github.com/noprompt/55b7e79887be24da458c

14:01 dnolen_: Bronsa: another case of :file, :line, :column leaking, not immediately obvious to me how to remove it.

14:05 Bronsa: ah, uhm, yeah that's problematic

14:07 noprompt: dnolen_ I'm considering decomposing the reader into a parser+emitter, that way source info could be attached to the parse tree & only optionally to the emitted forms, I suppose this should help cljs?

14:10 e.g. (parse "`foo") -> {:op :backtick :item {:op :symbol :form 'foo :line 1} :line 1}, (emit (parse "`foo")) -> ns/foo, (emit (parse "`foo") {:source-info? true}) -> ^{:line 1} ns/foo

14:11 so the cljs compiler could use parse, extract the source info & call emit on the parse tree w/o worrying about it being attached as metadata

14:20 dnolen_: Bronsa: I think I would prefer something simpler in this case for ClojureScript which is just an option to discard that stuff from backtick

14:20 I can't think of case where this would be problem given macros are written in Clojure

14:27 Bronsa: dnolen_: noprompt turns out the reader was already supposed to avoid attaching meta on syntax-quoted forms if meta consistend only of source-info but there is a bug.

14:28 ckirkendall: Bronsa - Nothing about the dissoc in reader/add-meta makes sense to me. The syntax-quote* should be on the dissoc meta.

14:28 Bronsa: ckirkendall: I just pushed a fix for that

14:29 dnolen_: Bronsa: k great

14:29 noprompt: done :)

14:30 ckirkendall: I don't think that fixes the problem.

14:30 Bronsa: dnolen_: so is this current behaviour acceptable for cljs? https://github.com/clojure/tools.reader/commit/0c4910fb59ee1ce39de48590ab851f75b86b4ffb

14:30 `foo -> ns/foo, `^:foo foo -> ^{:line 1 :foo true} foo

14:30 ckirkendall: nevermind

14:30 dnolen_: Bronsa: yes

14:31 Bronsa: cool, I'll release new tools.reader version then

14:31 dnolen_: Bronsa: thanks!

14:31 Bronsa: np

14:31 noprompt: awesome!

14:31 hurrah for edge cases!

14:33 dnolen_: how soon will we see that in master?

14:35 that seems like a pretty critical patch. :-)

14:36 Bronsa: 0.8.9 is out

14:36 noprompt: Bronsa: you rock!

14:37 SegFaultAX: Bronsa: Need to bump the README versions?

14:37 Bronsa: noprompt: perspective, I'm the one who put the bug there in the first place :P

14:37 SegFaultAX: yeah I'm doing that

14:38 dnolen_: noprompt: whenever tools.reader makes it to Maven Central

14:38 noprompt: I'll cut a new CLJS release just for this

14:41 noprompt: dnolen_: sweet. for some of the things we're doing that's going to reduce the output significantly.

14:41 Bronsa: no worries! :-)

14:43 ckirkendall: Bronsa: It feels odd that we are only looking for those keys and if a new key is ever added it will leak all of them. Should we not just strip them out before we syntaxt-quote them.

14:44 Bronsa: It fixes this case but feels fragile because it will leak all the keys if any new key exists.

14:45 Bronsa: ckirkendall: this behaviour is consistent with how LispReader does it

14:46 ckirkendall: https://github.com/clojure/clojure/blob/a989c01eed7ce29cc7672b7a402e4f335d792882/src/jvm/clojure/lang/LispReader.java#L855-L857

14:47 noprompt: bah! to hell with consistency! :-P

14:51 ckirkendall: Bronsa: This is a bit different we are leaking a bit more information including directory structures on the machine it created on. Maybe we should be using namespaced keys for this and striping them out.

14:51 noprompt: it seems like those keys oughta be namespaced or something.

14:52 ckirkendall and i not working together. this is purely a coincidence.

14:52 * noprompt knocks on wood

14:53 dnolen_: ckirkendall: noprompt: I don't think LispReader is going to add anymore of these and thus equally unlikely for tools.reader

14:54 more importantly code exists that relies on this stuff, it is effectively set in stone

14:55 Bronsa: ckirkendall: I can only assume you're talking about :file, that is handled the same way as by LispReader and binding *file* to nil is all it takes to strip it

14:56 noprompt: Bronsa: but how can we handle that when we're using cljsbuild?

14:57 Bronsa: noprompt: clojurescript controls tools.reader at that point

14:58 noprompt: dnolen_: for :advanced builds is that bound to nil?

15:00 dnolen_: nevermind.

15:00 Bronsa: noprompt: to be clear, I'm not opposed to adding a knob to tune what/where source-info metadata is attached in tools.reader, I just don't have the time for that right now. If you or ckirkendall or anybody else wants to submit a patch for that, be welcome to do so :)

15:01 noprompt: Bronsa: ok, that works. :-)

15:04 dnolen_: noprompt: just cut 0.0-2342, just waiting for a build executor on Hudson and of the course the delay to Maven Central

15:05 noprompt: dnolen_: thanks for the quick turn around. :-)

15:06 dnolen_: clojurescript is truly an anomaly.

15:07 foucist: anomaly?

15:07 noprompt: foucist: the patch/release cycle turn around is quick.

15:08 foucist: ah

15:08 noprompt: foucist: how many languages can you just say, hey, fix this now and it get's fixed now?

15:08 (inc clojurescript)

15:08 lazybot: ⇒ 1

15:08 foucist: heh

15:08 noprompt: :-/

15:09 foucist: (inc clojurescript)

15:09 lazybot: ⇒ 2

15:09 noprompt: really? *no one* has inc'd clojurescript.

15:09 hfaafb: (dec clojurebot)

15:09 lazybot: ⇒ 42

15:20 dbasch: what’s the standard way to do fmap these days, i.e. apply a function to the values of a map?

15:20 Bronsa: dbasch: I usually use reduce-kv

15:21 but I guess you can use zipmap and map over the vals

15:22 justin_smith: there is also (into {} (map (fn [[k v]] [k (f v)]) m))

15:25 TimMc: dbasch: clojure.algo.generic.functor/fmap

15:25 dbasch: TimMc: that’s where it went. Thanks.

15:27 eskatrem: noonian: hey, you tried to help me yesterday with a problem to update a field with mongo/monger

15:27 noonian: I fixed it, actually I tried to update the fields were ids are like {:id 1} by looking for {:id "1"}

15:28 justin_smith: amalloy: dunno if you saw in the scrollback, the heap usage issue was because the generation of odd count palindromes and even count palindromes diverged. By generating the input sequence twice I eliminated the issue.

15:29 that is, the range from 11 to 111 is not a huge problem, but the range from 12321 to 123321 is a bit more of a problem, etc.

15:32 dnolen_: noprompt: curious to hear what you think of the analysis changes :) they of course uncovered several issues in the standard library and core.async itself :P

15:32 also should make deftype/defrecord/reify/specify code way more pleasant to write

15:55 noonian: eskatrem: ah, that makes sense. I'm glad you figured it out!

16:03 amalloy: ah. thanks, justin_smith, i didn't see that

16:05 makes sense

16:07 eskatrem: noonian: yeah, I was really getting crazy over this.

16:08 jdeisenberg: What is the advantage of saying lein new app com.example/myproject vs. lein new app myproject ?

16:09 justin_smith: jdeisenberg: it sets up the directory structure properly

16:10 so instead of src/myproject/core.clj you get src/com/example/myproject.clj

16:10 and that saves some busywork of fixing it

16:11 jdeisenberg: justin_smith: thank you. I just see all the tutorials starting with "lein new app my-project" or such-like.

16:11 ...and then you get core.clj

16:12 Using the long notation appears to produce (ns com.example.myproject ...), which, I presume, is better because you avoid collisions with existing libraries,etc.?

16:13 justin_smith: it's actually meaningful

16:13 core.clj is just a filler

16:16 noprompt: dnolen_: sure. i suspect i'll have a chance to take a look at it when i make another round of patches to clairvoyant. hopefully that'll be soon. :-)

Logging service provided by n01se.net