#clojure logs

2013-09-04

00:04callenseangrove: gads that was ages ago. Irish pub on Clement by Laurel Heights.
00:30futilehey isnt someone in here a literature nerd?
00:31futilei just read The Raven to the kids and it was fantastic and im lookin for recommendations of similar short poems to read to them
00:39Xorlevfutile: Anything by Shel Silverstein. I'm also a fan of "Poetry 180", a compendium by Billy Collins who himself is a very accomplished poet.
00:41brainproxyfutile: I like Hopkins
00:42brainproxythere was a little collection of some of his poems, "Immortal Diamond"
00:43futilebtw what i loved mostly about the raven was all the alliterations and rhyming and perfect timing
00:44brainproxyprobably Hopkins most famous short poem: http://www.potw.org/archive/potw29.html
00:45brainproxy"Spring and Fall"
00:45brainproxyfor something more epic, Chesterton's "The Ballad of the White Horse" might fit the bill
00:45brainproxyhttps://en.wikipedia.org/wiki/The_Ballad_of_the_White_Horse
00:46brainproxyhttps://en.wikisource.org/wiki/The_Ballad_of_the_White_Horse
00:46futilechesty!
00:47futileoh man i didnt know he was a poet too, thought he was just a catholic hero
00:47brainproxyquite the poet
00:49brainproxyhis novel "A Man Who Was Thursday" is lesser read but is a real classic imo
00:49futileLOL: "The whole modern world has divided itself into Conservatives and Progressives. The business of Progressives is to go on making mistakes. The business of the Conservatives is to prevent the mistakes from being corrected."
00:49brainproxy*The Man...
00:49futilebrainproxy: thanks for this ill have to check him out more thoroughly :)
00:50brainproxynp
00:50futilei think he was one of the people who convinced me that you dont have to sacrifice intellectual integrity to believe in catholicism
00:50futile<3
00:51technomancya "lesser read"???
00:51lazybottechnomancy: Oh, absolutely.
00:51technomancybollocks
00:55futiletechnomancy: you can only say that if you lived in UK for > 80% of your life
00:56technomancyI grew up in the commonwealth; leave me alone =P
00:56futilehey i dont make the rules
00:57futile(inc brainproxy)
00:57lazybot⇒ 2
00:59brainproxywhat is wrong with "lesser read" (I'm a yank btw)
01:01technomancyI think Thursday is his best work
01:01futilewelp, time to eat cookies and try to make progress in this immutable recursive descent Clojure parser.
01:02futiletechnomancy: depends what he meant by "lesser read", could very well mean less popular
01:02amalloyfutile: is there a reason you aren't just using something already built? there are some excellent parsers in clojure
01:02brainproxyfair enough; most people I've met that have even heard of Chesterton have read "Orthodoxy" or his biography of Francis, the Father Brown novels, etc.
01:02amalloyeg, instaparse arrived on the scene to great fanfare a couple months ago, and looks great
01:02seabreparsatron is pretty cool
01:03brainproxyI've met few that have read Thursday, but that may be Americans
01:03futileamalloy: well part of it is that its a learning experience
01:03futileamalloy: thats probably a big part. another part is that i want to preserve source locations for each token and i didnt think any existing ones do it fully.
01:06futileamalloy_: and thirdly learning another parser lib seems like it might be just as difficult as writing a clojure parser
01:07brehautfutile: do you know BNF? you know instaparse
01:07futilei do not
01:07futilenot well enough to write it reliably
01:09technomancybrainproxy: oh, I interpreted "read" as a noun rather than a verb
01:09technomancywhich is I guess what futile said
01:09technomancyas you were
01:09futiletechnomancy: no i also interpreted it as a noun
01:10futiletechnomancy: i still thought "a lesser read" could regard the "popularity" attribute rather than "quality"
01:10futilethats how i interpreted it.
01:18callenbrehaut: Instaparse is maaaaaaaagic
01:18callen<3
01:19futileis instaparse self-hosting yet?
01:19callenfutile: you'd probably learn more from learning an existing parser through-and-through than you would writing a recursive descent parser.
01:19callenthe old saw about recursive descent parsers was that those were the lines simple enough to be written in sharpie on the side of a 2 liter coke bottle.
01:20callenthose were the parsers*
01:21futilecallen: i wrote a simple lisp parser in C once successfully
01:21futilei just think it was really badly done and i want to learn how to do it smarter.
01:21futileso im reading about it
01:22brehautfutile: https://github.com/brehaut/inc-clojure-brush/blob/master/shBrushClojure.js#L64-L385
01:23futilebrehaut: thats similar to what i had before, but now i want to do it in idiomatic clojure
01:23brehautidiomatic clojure would be dont write a recursive decent parser by hand when there are good tools already in existence ;)
01:24futilei came up with this trick to emulate "read" and "peek"... (partition 2 1 [:end] string)
01:34seabreI can't read "came up with this trick" without thinking about this and its variations: http://www.oneweirdkerneltrick.com/paperfigs/vapnik.jpg
01:34seabreThanks internet.
01:37futileseabre: parsers *hate* me!
01:38seabrelol
01:38futilebecome a parent in 280 days with this one weird trick
01:39futileaw its not on knowyourmeme
02:13futilegoing unconscious for few hours
02:14RaynesWhere will you be when the LSD hits?
02:15Rayneshttp://imgur.com/r/funny/Fr3V0St
03:42hhenkel_Good morning everyone, what is the best way to check a string for a substring or regex?
03:44fredyr,(.contains "coool" "ool")
03:44clojurebottrue
03:45hhenkel_fredyr: oh, that's easy...I was thinking about much more complicated stuff...thanks!
03:45fredyr:)
03:47hhenkel_fredyr: Is that also usable with a regex?
03:47fredyr(.matches "ceaol" "c[aeo]{3}l")
03:47fredyryou'll have to use matches then
03:47fredyr,(.matches "ceaol" "c[aeo]{3}l")
03:47clojurebottrue
03:48hhenkel_fredyr: ah, okay. Thanks again!
03:48fredyrsure np
03:50fredyrthe java String docs is useful for these things btw
03:50fredyrhttp://docs.oracle.com/javase/6/docs/api/java/lang/String.html
03:51hhenkel_fredyr: another question regarding "matches", you're not using #" " syntax there for regex. is that because it is a java function.
03:53hhenkel_Oh, i meant ? not . at the end of the sentence... ;)
03:53fredyryes the String api takes strings for regexes and not java.util.regex.Pattern
03:56hhenkel_okay
03:58fredyrthe Patterns are great when you want to take apart a string
03:58shaungilchristwhat is state of the art for cljs pprint?
04:00fredyr,(let [[a b c d] (re-matches #"(c)([aeo]{3})(l)" "coool")] [a b c d])
04:00clojurebot["coool" "c" "ooo" "l"]
04:04sheldonhg'damn! clojure's map applies over multiple collections. hot
04:15ambrosebs_bbloom: check the mailing list...
04:52sheldonhis there a core function that does (partial apply concat)?
05:08ddellacostasheldonh: just coming to Clojure?
05:08ddellacostaoh, I guess you wrote that like an hour ago, d'oh
05:08ucbheh
05:08ddellacostahaha
05:09ucbI actually read sheldonh's comment as hash-maps being applicable to multiple collections :(
05:14sheldonhddellacosta: yup :)
05:15ddellacostasheldonh: all I wanted to say was, I expect you'll have a lot of those "hot!" moments from now on. ;-)
05:15ucbdoes nrepl support who-calls?
05:15ddellacostaucb: I didn't think of that...
05:15ucbnrepl.el even
05:15ddellacostaucb: sorry, what's who-calls?
05:16ucbddellacosta: I have a history for misreading things
05:16ddellacostaucb: haha, I do too, so don't feel bad.
05:16ucbddellacosta: say you're looking at the definition of a function, you want to know where it's used, i.e. who-calls the fn?
05:16ddellacostaucb: pooh, gotcha. Yeah, I dunno, sorry. But that sounds pretty freaking handy.
05:16ddellacostapooh = oooh on spellcheck
05:16ucbthat's because it is :)
05:17ucbheh
05:17ddellacostahahaha
05:17ucbmy phone's spellchecker corrected hope to hippie
05:17ddellacostanice
05:17ddellacostasomething poetic about that one
05:17ucbended up telling my friend "hippie you can come"
05:17ddellacostahahahaha, seriously, just laughed out loud at that
05:17ddellacostagood thing I had nothing in my mouth
05:17ucbI laughed too
05:17ucbhe never texted back
05:17ddellacostaucb: hahahahahahaha
05:17ucbso there goes another relationship ruined by technology
05:18ddellacostaucb: he's lost
05:18ddellacostahahaha
05:18ucbheh
05:18ddellacostabrilliant
05:20fredyr:)
05:20clgvcan I query attributes of nested maps in monger?
05:25NeedMoreDesuI use http://stackoverflow.com/questions/9694754/clojure-how-to-get-the-path-of-a-running-jar-root-source-directory rplevy's solution and have problems with whitespaces. What can I do?
05:27ddellacostaNeedMoreDesu: what do you mean, problems with whitespaces?
05:28NeedMoreDesu%20 in their places
05:29ddellacostaNeedMoreDesu: still confused. %20 is where?
05:30NeedMoreDesu#<URL file:/D:/folder1/folder2/new%20folder/xxx-0.1.0-SNAPSHOT-standalone.jar>
05:31NeedMoreDesuIt's "new folder"
05:31ddellacostaNeedMoreDesu: okay, so, you need that as a string with spaces replacing the %20?
05:32NeedMoreDesuHmmm.. solving problem so directly? Never thoght about that lol.
05:33ddellacosta,(java.net.URLDecoder/decode "new%20folder")
05:33clojurebot"new folder"
05:33ddellacosta…for example. Still not sure exactly if that does what you need, but it's the simple answer as to how to get those %20s (and anything else URL encoded) out of the string.
05:34ddellacostaNeedMoreDesu: are you in Japan, btw, or is your handle unrelated to Japanese?
05:35hhenkel_How would one change values of a vector? Situation is, I got a ref to a map and within that map I got a vector. Now I'm checking if the values matching a specific regex and if it does, I want to change the value.
05:35NeedMoreDesuddellacosta: might be related, since I have japanese locale.
05:35hhenkel_I tried the following, but assoc seems to be the wrong thing: (let [bla ["${actions.FreePhysicalMemorySize}" "${actions.FreeSwapSpaceSize}" "${actions.TotalPhysicalMemorySize}"]] (doseq [x bla] (if (.matches x "^\\$\\{.*\\}") (let [tmp-atom (atom x)] (swap! tmp-atom assoc tmp-atom "blabla")))))
05:36ddellacostaNeedMoreDesu: just curious, since I'm in Japan. Always interested to hear if there are an folks in Japan using Clojure.
05:36hhenkel_What would be the best solution for that?
05:36ddellacostahhenkel_: please use refheap, do not paste code into IRC
05:36ordnungswidrighhenkel_: (if (.matches x #"...") blabla x)
05:37ddellacostahhenkel_: also, don't know why you need an atom for that, just use loop and recur
05:37NeedMoreDesuddellacosta: Sorry, I'm not from japan, just used it to avoid crash problems in some jp games >_>
05:37ordnungswidrighhenkel_: together with map: (map #(if (= "foo" %) "bar" %) ["some" "foo" "bar" "baz"])
05:37ddellacostaNeedMoreDesu: ah, okay...haha
05:37hhenkel_ordnungswidrig: ? I learned earlier on that this is a java function and therefore string regex are used. This part works.
05:38AnderkentNeedMoreDesu: what are you planning to do with the url? the path is right for a folder with spaces in it, it's how spaces are encoded for urls
05:38ordnungswidrighhenkel_: you want to update some values in a list, right?
05:38hhenkel_ddellacosta: Thouht if I want to make a persistent change to a list I need a atom or ref, don't i?
05:39hhenkel_ordnungswidrig: yes.
05:39ddellacostahhenkel_: sure, but if you are doing it inside a doseq it defeats the purpose
05:39ordnungswidrighhenkel_: the most easy is to use map, like above, you can then use update-in to update a list which is a map vaue.
05:39AnderkentNeedMoreDesu: if you want to get a filesystem path from that, do (.getAbsolutePath (File. my-url)) for example
05:39NeedMoreDesuAnderkent: I used it as input to clojure.java.io/file. ddellacosta's solution works.
05:40Anderkentyou can just pass it to file without modifying it
05:40sheldonhddellacosta: fortunately, i dipped into haskell last year, so it's not completely overwhelming. someone here recommended 4clojure.com, which i've been enjoying enormously
05:40clojurebotIt's greek to me.
05:40ordnungswidrighhenkel_: i'll put together an example, wait a minute
05:40ddellacostasheldonh: I love 4clojure, I gotta get back to it myself. Welcome! I need to get into Haskell myself, now that you mention it...
05:40hhenkel_ordnungswidrig: okay, thanks. my ? was regarding the (.matches ...) as that part works for me.
05:41sheldonhddellacosta: it's not a great first functional language, imho, because you have to absorb functional programming and algebraic types all at once. but with clojure under your belt, i bet you'll have a lot of fun with haskell :)
05:41clgvhhenkel_: there is `re-matches` to get rid of the unnecessary interop
05:42ddellacostasheldonh: ah, good to know. Yeah, I've heard it's kind of a major mind bender. Looking forward to learning more.
05:42NeedMoreDesuhhenkel_: you change values of a vector with assoc, just like maps.
05:42NeedMoreDesuassoc, get, update-in works
05:42hhenkel_clgv: okay, fredyr pointed me to .matches earlier on.
05:43clgvhhenkel_: for basic takss look for a clojure function first ;)
05:43clgv*tasks
05:43ordnungswidrighttps://www.refheap.com/18292
05:43hhenkel_clgv: I had much more complicated stuff in mind, so that was allready a good thing... ;)
05:44ordnungswidrighhenkel_: saw that link?
05:44clgvhhenkel_: the matches is likely to be slow if used very often because the compiler does not know that `x` is a string. the clojure function avoids this for you
05:45clgvthe `(.matches ...)`
05:45sheldonhddellacosta: advice from my limited haskell experience: stop at least 2 hours before bed time :)
05:45amalloythere's really no reason to use .matches and an ugly double-escaped string instead of re-matches and a regex literal
05:45hhenkel_ordnungswidrig: Yes, thanks. I think it takes me some time till I totaly understand what going on. Thank you!
05:45ordnungswidrighhenkel_: more ideomatic would be https://www.refheap.com/18293
05:46ordnungswidrighhenkel_: decompose your problem!
05:47ordnungswidrighhenkel_: 1.) define a function that replaces the regexed-matches. 2.) define a function that maps this function over the vector 3.) apply this second function on the map value using update-in
05:48hhenkel_ordnungswidrig: Divide and conquer...I'll try but currently I'm fighting with the missing knowledge vocabular.
05:48clgvhhenkel_: do you want to build a templating system? if so, you should know there are already several libs for that
05:48ordnungswidrighhenkel_: we're here to help
05:49ordnungswidrighhenkel_: you need to understand, that you cannot update a list or vector. You will always be returned a new instance.
05:50ordnungswidrighhenkel_: to be honest, there are ways for in-place modification but these should be reserved for performance sensitive application
05:50ddellacostasheldonh: point taken!
05:50hhenkel_clgv: Nope, I'm trying to learn clojure and what I'm trying to do is 1) read an edn, 2) look at all values of the config I read if they are like "${firstpart.secondpart} 3) go to {"firstpart{ "secondpart" "test"} and get the value test and insert it instead of the "variable".
05:50clgvordnungswidrig: well phrased like that you cannot update any immutable data structure ;)
05:51ordnungswidrigclgv: huh, I first read "immortal".
05:51clgvhaha
05:52hhenkel_ordnungswidrig: I'll try to find my way around the immutible data structures but I'm spoiled by oop... ;)
05:52clgvordnungswidrig: I think you meant that you cannot update lists efficiently meaning in constant time.
05:52clojurebotTitim gan éirí ort.
05:52hhenkel_I'm off for lunch. Read you later.
05:52clgv*elements in lists I wanted to say
05:52ordnungswidrigclgv: you cannot?
05:53clgvexcept from the first element ok ;)
05:53Apage43I get to spend this week implementing mutable data structures that will be hit from multiple threads, in C++. I am not excited.
05:53hyPiRionApage43: oh dear
05:54clgvApage43: is there nothing in boost for that?
05:54hyPiRionApage43: For hash maps, do the HAMT/Concurrent tries from Bagwell, http://skillsmatter.com/podcast/scala/parallel-algorithms-data-structures
05:55Apage43The guy here needs to be an ordered map of some sort
05:57hyPiRionoh dear =/
05:57hyPiRionIt's possible with the HAMTs, but it's a bit of thinking I *think*.
05:58Apage43If I could manage both figuring that and grokking how to do this well with no GC, it'd really be perfect, since one of the things we want is to be able to get a snapshot of the thing.
06:00hyPiRionOh, then the concurrent tries are a great fit. But the GCing is a bit iffy, yes.
06:00hyPiRionApage43: A single week only? =/
06:01Apage43possibly more =P
06:01Apage43(realistically more)
06:01Apage43but the made up number is a week
06:25ddellacostawhat does the double-dot function do in clojurescript?
06:25ddellacosta(.. something fn1 fn2) ?
06:26ddellacostait seems a bit like doto or -> but not sure exactly what is going on
06:26ddellacostacan't find it in docs
06:26hyPiRionddellacosta: macroexpand it
06:27hyPiRion,(macroexpand-1 '(.. something f1 f2))
06:27clojurebot(.. (. something f1) f2)
06:27hyPiRion,(clojure.walk/macroexpand-all '(.. something f1 f2))
06:27clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>
06:27ddellacostahyPiRion: um, can I do that with CLJS?
06:27hyPiRionddellacosta: I will guess the macro also exists in cljs
06:28hyPiRionit's just a chaining of .call functions
06:28ddellacosta…is it in Clojure too? only ever seen it in CLJS
06:28ddellacostaoh well, look at that
06:28ddellacostanevermind.
06:29ddellacostahyPiRion: I guess I don't see why you'd use this over ->
06:29clgvyes it is. pretty useful :D
06:29ddellacostahyPiRion: I guess it's more concise if you are doing java interop
06:29hyPiRionyeah
06:29ddellacostawell then, I learned me somethin' new. Thanks hyPiRion.
06:30hyPiRionnp
06:31hyPiRion,(.. "string" (substring 2) (equals "ring"))
06:31clojurebottrue
06:42hhenkel_ordnungswidrig: regarding the immutability. What would you suggest then when I read a edn file as a config and want to manipulate the config? I thought of having a ref to the config...
06:43ordnungswidrighhenkel_: what does manipulate mean? do you need to change once (after reading) or again and again?
06:43hhenkelordnungswidrig: once after I read the config from file I want to make some kind of "variable substitution".
06:44ordnungswidrighhenkel: then you build a function that returns the data substituted
06:45clgvis there already a lib implementing a query language similar to the stuff for DOMs for nested clojure data structures?
06:46ordnungswidrigclgv: get-in?
06:47clgvordnungswidrig: no that is only map/vector access.
06:48hhenkelordnungswidrig: okay, so I build a function returning the altered data and assign it to a new binding? Or I read the config in a function and also alter it there and use that to initially bind the data to a name?
06:48ordnungswidrigI would simple bind the final result like that (def config (substitute-all-the-vars (read-config-from-file "config.edn")))
06:49hhenkelordnungswidrig: hmm, okay that sounds reasonable...I find it really hard to switch my thinking on how to implement stuff.
06:50ordnungswidrighhenkel: once you switched it will be even harder to look back. :)
06:52hhenkelordnungswidrig: It allready starts, currently I have to teach python to one of my coworkers.... :(
07:01hhenkelordnungswidrig: one final question regarding the code you provided. In the example you know where ("[:a]") to alter the text. In my situation I have to loop through the whole map ("tree") to find the values that I want to alter. Is there also a nicer way to do it?
07:03ordnungswidrighhenkel: you need up changes multiple keys?
07:04clgvhhenkel: if it is a map-tree you can use clojure.walk but be careful with metadata
07:04ordnungswidrigthere is also fmap in the ns algo.generic
07:04hhenkelordnungswidrig: yes, as it is a "user" provided config there maybe the chance that more "variables" need to be altered.
07:06ordnungswidrig,(clojure.algo.generic.functor/fmap inc {:a 1 :b 2})
07:06clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.algo.generic.functor>
07:11hhenkelclgv: Looking at the description at clojure docs I don't understand how to enhance the example with the multiply 10 so that it works with a "tree"
07:14clgvhhenkel: dont know how your "tree"s are defined
07:18hhenkelclgv: more or less like this: { :hosts { :host1 { :protocol "http" :port 9101 :actions [ "action1" "${actions.action2}" ]}}}
07:18clgvhhenkel: and you want to replace only leaf-nodes?
07:19hhenkelMy current assumption is that only values could contain "variables" to make life easier.
07:19hhenkelBut in theory it could also be possible to have keys that need to be replaced.
07:22clgvhhenkel: well clojure (pre/post)walk will walk all clojure collecions so these are inner nodes and all non-collections (say "atoms") are leafs
07:23clgvhhenkel: prewalk calls the given function before walking the children, postwalk does so after.
07:26Anderkentclgv: you mean clojure.walk/walk? I don't think that goes into maps
07:26clgvAnderkent: it does
07:26Anderkent,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})
07:26clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>
07:26Anderkentblah
07:26clgv&(use 'clojure.walk)
07:26lazybot⇒ nil
07:26Anderkent,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})
07:26clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>
07:26Anderkent,(use 'clojure.walk)
07:26clojurebotnil
07:26Anderkent,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})
07:26clojurebot[:a {:b $foo}]\n[:c {:d :f}]\n{:a {:b "$foo"}, :c {:d :f}}
07:27Anderkentwalk is for sexps afaik
07:27clgv&(postwalk (fn [x] (if (integer? x) (inc x) x)) {:a {:b 1}})
07:27lazybot⇒ {:a {:b 2}}
07:27clgvAnderkent: there you go ^^
07:28Anderkentah, I see. So the inner given to walk should recurse, I suppose
07:28Anderkent,(clojure.walk/postwalk-replace {"$foo" "bar" :c :notc} {:a {:b "$foo"} :c {:d :f}})
07:28clojurebot{:a {:b "bar"}, :notc {:d :f}}
07:29Anderkentcool
07:29hhenkelclgv: so, prewalk executes before it traverses and postwalk first traverses and then executes?
07:30clgvhhenkel: sounds about right, yes
07:31Anderkentalso look at how ugly walk is because of this stupid idea that emptying a MapEntry gives nil.
07:31clgv&(pewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (integer? (val x)) x) x)) {:a {:b 1 :c "bla"}})
07:31lazybotjava.lang.RuntimeException: Unable to resolve symbol: pewalk in this context
07:31clgv&(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (integer? (val x)) x) x)) {:a {:b 1 :c "bla"}})
07:31lazybot⇒ {}
07:32clgv&(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (or (map? x) (integer? (val x))) x) x)) {:a {:b 1 :c "bla"}})
07:32lazybot⇒ {}
07:32clgvok nvm
07:33clgv&(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (or (map? (val x)) (integer? (val x))) x) x)) {:a {:b 1 :c "bla"}})
07:33lazybot⇒ {:a {:b 1}}
07:45sheldonhwhen you use defn in 4clojure, it says "You tripped the alarm! def is bad!" i have been assuming that it means "def is bad in 4clojure". yes?
07:46Anderkentsheldonh: yes, sandboxed environments dont let you def stuff
07:46Anderkent,(def bad-boy 1)
07:46clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
07:46sheldonhthanks :)
07:49clgvAnderkent: not necessarily, you can setup your sandboy with clojail allowing `def` and just cleaning up all namespaces every 10mins or so
07:50clgv*sandbox
07:50clgvAnderkent: would be really useful. but both clojurebots mistrust us too much to do that ;)
07:51sheldonhyou server, your rules ;)
07:55clgvsheldonh: btw. 4clojure literally copies your code at the position of the __
08:01sheldonhclgv: three cheers for referential transparency :)
08:02sheldonhdestructuring lazy, infinite sequences. hohoho!
08:12sheldonhit'll be very interesting coming back to my first round of 4clojure solutions, armed with the learning from same
08:17clgvno clojure 1.5 on 4clojure :(
08:22borkdudeIs it possible to enforce a constraint on a string field in Datomic, to be always lowercase?
08:24clgvborkdude: are there any constraints for attribute values possible?
08:24borkdudeclgv don't know, this is what I'm asking I guess :)
08:25clgvborkdude: well, if it were than the had to be part of the schema right?
08:25augustlborkdude: no, you need to wrap datomic to handle that
08:25augustlthe datomic peer lib compares more to the raw mysql lib than an actual "useful" data storage lib :)
08:26augustlI hope they add validation tx functions at some point though, not just fact creation tx functions
08:27clgvaugustl: since you seem to have some datomic value let me ask the following question: when exactly do transactions in datomic fail?
08:27augustlyou can throw exceptions in your own tx functions. There is also some validation in place. I'm not sure if it's all explicitly documented.
08:28augustlbut if you refer to a symbol/attribute that doesn't exist you'll get an error, and so on
08:28ro_stis there a variant of group-by that removes the key from the seq?
08:29clgvaugustl: ok I meant failure for trying to commit confliciting changes to the same entity for example
08:30augustlclgv: there's not a lot of conflict that can happen :)
08:30augustlin more recent versions you'll get a failure if you transact in a fact that matches the existing fact (i.e. set the username to what the username already is set to)
08:31clgvaugustl: hmm. so if to peers hammer at the same attribute with entirely different values I have different points in the db history where the value was correct for one of them
08:31clgv*two peers
08:32augustlclgv: the transactor gets to decide which one wins, since writes are single threaded
08:32clgvor does a transaction fail when I try to update an entity based on the db at time point 1 and the db already is at timepoint 5?
08:33augustlwhat you describe is optimistic locking - you'd nede to implement that yourself (I've done it for one of my systems once)
08:34clgvhmm well I think I need a better description how the transactions work in datomic. one video and the webpage were not sufficient it seems
08:34augustla tx consists of the facts only, datomic doesn't care about the state of the peer that created it
08:34augustlclgv: in short, it's a single queue of transactions that gets processed one at a time
08:35augustlthis is the only way to guarantee 100% consistency
08:35clgvyeah so much I know.
08:35ro_styou can write functions that run inside your tx which can query into the database as it is during that tx, and you can throw exceptions if they don't like what they see
08:36augustlclgv: my Datomic knowledge is accreted through #datomic, various videos, blog posts, and having talked to Rich Hickey at a conference once :)
08:36clgvso the commiters need to make sure that they do not post conflicting facts?
08:36augustlclgv: "conflicting facts" - what do you mean by that?
08:36clgvaugustl: in a logic sense of the problem domain of the facts.
08:36ro_stclgv: you can always go back in time to see what the facts were in the past
08:37augustlthe only conflict I'm aware of is that you transacton contains a fact that matches the existing fact
08:37augustlanything else is just written
08:37clgvro_st: yes but that wont help if most of the time two peers write conflicting facts such that the problem model in the db is rubbish
08:37augustlso the conflict is in your interpretation of the data, not in datomic itself?
08:38clgvyes
08:38ro_stclgv: unless you had transactor functions that checked your problem model prior to commit
08:38augustlalso keep in mind that a transaction is fully atomic. You won't see some values from one transaction and other values from another
08:38ro_styou can give your transactor process extra jars in its class path if you need to call out to domain logic
08:38clgve.g. you calculate the average of a set of numbers and then someone change this set of numbers right before your commit
08:38augustl(assuming you have two transactions for the same attributes and the same entities, but setting different values)
08:38augustlclgv: that you would have to do in a transactoin function to be able to have it consistent
08:39ro_stif you really, really wanted to, you could validate your whole problem model / database inside every transaction
08:39clgvaugustl: so for large calculation you would have a compare and swap function as transactor function or similar?
08:39ro_stnothing stopping you from doing that. it'll make transactions much slower to process, of course, but you would always have a consistent model
08:40ro_stif your checks are inside a transactor function, the data *can not change* until that transaction completes or errors out. transactor is serial. one at a time
08:40augustlclgv: the transaction function is pure. It gets the database as of the point right before that transaction (single threaded so it's 100% consistent) then you query that database, compute your value, and from the tx function return your transaction, such as [[:db/add the-entity-id :the-attr computed-value]]
08:41augustlin addition to the db it gets passed any arguments, so if you in a peer do [:my-fn 123] you'll get the db and 123 passed to the tx fn my-fn
08:41augustlsee: stored procedures ;)
08:42clgvaugustl: ah ok interesting. thank you :D
08:42augustl..which is why datomic is probably not a good fit if you need a lot of writes and this computation takes a long time
08:42clgvaugustl: that means stored procedures are used more often than in sql databases?
08:43augustlclgv: yeah. You can't do chatty client-side transactions with datomic
08:43ro_styou'd only want to use transactor functions when you need consistency. otherwise, do your work in the peers
08:44augustlonly transaction functions with isolation level 9000 :)
08:45augustlan alternative is to do something like reading the db as of now, which is immutable and "consistent", compute the compound value somewhere, and store it in a different database than datomic
08:45augustlor perhaps use a cache instead of storing it normalized in the db
08:46clgvaugustl: datomic stores `many`-relation attributes as sets right? so I can not have duplicate values in there?
08:47ro_styou can have multiple entities with the same value on a given attribute, and then relate those entities as a set
08:48ro_steg a group entity with 3 user entities all with the :name "Mike"
08:48clgvok let me rephrase: I need to get multiple values that are equal for that attribute for the following calculations
08:48clgvis :db.cardinality/many only possible for :db.type/ref?
08:49augustlclgv: you can have cardinality/many for any attribute
08:49ro_stit's totally possible for any of the types you can use
08:49clgvI want an attribute with :db.type/double and :db.cardinality/many
08:49augustlI'm not actually sure about how equality is determined. I would guess the same as Clojure sets
08:49clgvaugustl: that would be a problem
08:51augustlclgv: you could always use entities, of course, and store the doubles as attributes on that entity
08:52clgvwith size explosion :/
08:53ro_stentities are basically just longs, clgv
08:54clgvro_st: that means I double the size per double value...
08:55ro_stway more than double the size
08:55ro_stdatomic stores each datom at least 3 times. and each datom is four scalar values
08:56augustlclgv: keep in mind that entities are not stored in Datomic. Entities are just derived from the facts in the index
08:57augustlwhich is why you get an emity entity instead of nil when you do (datomic.api/entity db some-eid-that-does-not-exist)
08:57augustlso actually the storage space is pretty much the same :) You just have two facts instead of one - one for the ref, and one for the double value
08:59clgvequality semantics are the same as in clojure. so no choice but to store them as byte array :(
09:01augustl..or to use an extra entity :)
09:02clgvno. that is more complicated than just one call to convert to byte-array and one call to convert back to double-array
09:03clgvI dont want to query for the single values anyway.
09:03augustlclgv: sure thing, just wanted to be pedantic ref "no choice but to" :)
09:03clgvI'd wish all 4 clojure data structures could be plain values
09:05augustlwould be nice if datomic could store lists and such, but you'd soon get problems with the fact that Datomic doesn't like large values
09:06clgvaugustl: yeah that should be fixed as well. ;)
10:24clgvaugustl: 2 seconds per transactions for importing data into datomic seems slow to me. what am I doing wrong
10:24clgv?
10:26augustlclgv: depends on your transaction and your data
10:26augustlwhat kind of workload are we talking about?
10:27clgvaugustl: the transaction is a tree of entities summing up to 1,3MB when serialized to bytes
10:27augustlsounds about right to me, maybe, perhaps :)
10:27augustlI've got little experience with large transactions
10:28clgvshould I try to put more then one of those entity trees in the transaction?
10:28augustldo you have any large attributes? Or is it you I discussed this with in #datomic yesterday? :)
10:28augustls/attributes/single values/
10:28clgvI'd have to import for 2 days with that speed
10:29clgvaugustl: yes that was me. I got rid of the large binary attributes. now all binary attributes are below 20K
10:30clgvaugustl: I use the recommended setting ratios for 4g RAM for 8g
10:32augustlsounds like a job for the people that know what they're talking about. That would be the relevance peeps in #datomic. All I can say is that datomic trades write speed with consistency
10:43hhenkelI'm still struggling with postwalk, what do I have to do to get back the altered tree and not nil? https://www.refheap.com/18305
10:47Anderkenthhenkel: you must return the unaltered node if your condition doesn't match
10:47clgvhhenkel: your else-case has to return something
10:47Anderkentright now you're saying 'if it's a string replace test with TEST, otherwise return nil'
10:48Anderkentalso, never ever make one-armed ifs. If you want nil for the else-clause, use when.
10:51clgvhhenkel: https://www.refheap.com/18308
10:58ddellacostawhat's the inverse of filter?
10:59clgvddellacosta: remove
10:59ddellacostaclgv: d'oh, obvious. Many thanks!
10:59clgv&(remove odd? (range 10))
10:59lazybot⇒ (0 2 4 6 8)
10:59ddellacostalazybot just made a cool guy smiley at me.
10:59ddellacostacurse you lazybot!
11:00Anderkent(0
11:00clgv8)
11:07hhenkelclgv: Your code gives me errors, it seems like there is one bracket in the wrong position.
11:07hhenkelBut I think I got it fixed...now I have to check what you changed...
11:08hhenkelAnderkent: okay...I'll try to remember that.
11:08clgvI added one `%` and removed the unnecessary `do` - it was supposed to end up in the else branch of your `if`
11:11hhenkelclgv: Thanks, it is now working, very good hint that the else is causing the nil, wasn't aware of that.
11:14noncomis this an intended behavior of (ns)? : https://www.refheap.com/18311
11:15noncomwhen i got hey/pool and it fully behaves like a namespace inside a namespace, I was surprised
11:15gfredericksnoncom: I don't think it's a "namespace inside a namespace", it's just a namespace that happens to have a / in its name
11:16gfrederickswhich would probably cause you some trouble but is apparently not checked for
11:16sandbagsanyone recommend a CSV parsing library? I can see 3 on clojars.org but no details (e.g. api docs) about any of them
11:16gfrederickssandbags: data.csv works fine for me
11:17sandbagsamusingly that is not one of the ones listed by clojars :)
11:17noncomgfredericks: why does it create hey/pool and not pool as i have specified?
11:18gfredericksnoncom: because of how ` works
11:18sandbagsah, i see data.csv is at maven
11:18gfredericks,`pool
11:18clojurebotsandbox/pool
11:18Anderkentnoncom: because ` namespaces all symbols
11:18gfredericksnoncom: ^
11:18sandbagsthanks gfredericks
11:18gfrederickssandbags: np
11:18noncomok, how do i make it in the macro not to be prepended there?
11:18Anderkentuse ' not `
11:18gfrederickssandbags: yeah the core libs don't get deployed to clojars
11:18Anderkentor do `~'symbol
11:18sandbagsis data.csv a core lib?
11:18Anderkent,`~'pool
11:18clojurebotpool
11:18gfrederickssandbags: yeah
11:19sandbagsi'd have expected it to be core.data.csv or somehting
11:19sandbagsmaybe i am missing something about the convention
11:19gfredericksAnderkent: `~' is an interesting emoticon
11:19sandbagswas there some way i could have known it was a core lib?
11:19noncomwhat is the diff between ' and ~' in this case?
11:19gfrederickssandbags: the naming convention includes data.*, java.*, and maybe some others
11:19Anderkentthe difference is that with ~' everything else will be properly namespaced, whereas with ' nothing will be namespaced
11:19clojurebotOk.
11:19sandbagsah, so it's kind of an informal thing
11:19sandbags"learn the prefixes for core"
11:19gfredericks:)
11:19sandbagsok
11:20Anderkent,`(+ 1 ~'nothing)
11:20clojurebot(clojure.core/+ 1 nothing)
11:20sandbagsalso am i missing where this stuff is documented?
11:20Anderkent,'(+ 1 nothing)
11:20clojurebot(+ 1 nothing)
11:20gfrederickssandbags: the clojure github page would give you a sense for what exists
11:20sandbagsor is the documentation "read the source" ?
11:20gfrederickssandbags: I don't know of a good resource for contrib libs except for that diaspora page
11:21sandbagsokay i'm just used to (spoiled maybe) by ruby gems where, typically, the rdoc is published
11:21gfredericks$google where did contrib go
11:21lazybot[Where Did Clojure.Contrib Go - Clojure Development] http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go
11:21sandbagsso at least you tend to have easy access to the api docs
11:21noncomhehe, well, thanks! i'll go do more things with that.. :)
11:22gfrederickssandbags: the rdocs are all published in the same place?
11:22Anderkentwait what? data.csv is not a core lib. it lives in a separate jar
11:22gfredericksAnderkent: "contrib lib" is probably what I should have said
11:22gfredericksI did not mean that it's distributed with the clojure jar
11:22sandbagsokay so it's easy enough to rustle up the docs
11:22noncom,'(+ 1 'nothing)
11:22clojurebot(+ 1 (quote nothing))
11:22Anderkentyeah that's kinda different.
11:23sandbagsi do wish more of them came with examples, but i guess you can always find something to complain about :)
11:23noncom,'(+ 1 ~'nothing)
11:23clojurebot(+ 1 (clojure.core/unquote (quote nothing)))
11:23Anderkentsandbags: I don't think there's a 'list of all clojure.org' projects, but they are usually well documented. data.csv doesnt have that rich an api nayway: http://clojure.github.io/data.csv/
11:23gfredericksnoncom: shameless plug: http://www.infoq.com/presentations/macros-clojure-west-2013
11:24AnderkentI guess you can just take a look at https://github.com/clojure to see all org.clojure/* projects
11:24sandbagsAnderkent: yep i was able to rustle that page up (but thanks, in any case, for the link) i guess it's maybe a case of finding my feet
11:24sandbagsand having the right instinct about where to look
11:24Anderkentmy workflow when I find a lib is usually
11:24sandbagsalthough i would have thought that some kind of consolidated search over clojars and maven would be useful
11:25hanDerPederdoes anyone know if clj-webdriver is actively maintained?
11:25Anderkentlein try org.clojure/data.csv , (require '[clojure.data.csv :as c]) (c/<tab completion>)
11:25Anderkentand see what comes up :P
11:25gfrederickssandbags: well I don't think "maven" is a thing you can search over. But it could be better than it is, yeah
11:25sandbags:)
11:25sandbagsgfredericks: i meant search.maven.org
11:25Anderkentyou can search maven, but that's not usually what you want to do
11:26Anderkentand you can't trust mvn central anyway
11:26sandbagsgood to know :)
11:26xeqiI believe sonatype is calling that "central"
11:26Anderkentcentral's broken by design, and you should really strive to use sonatype/clojars instead of central whenever you can
11:26sandbagsbtw Anderkent, why do you quote your vector in that require?
11:27Anderkentsandbags: because it's not in the ns macro
11:27xeqiAnderkent: can you expand on the "broken by design" ?
11:27Anderkentxeqi: there's no access control. Once you have push to mvn central, you can push to any group/artifact, and even overwrite versions
11:27sandbagsAnderkent: (answer-expand-1 "because it's not in the ns macro")
11:28xeqiAnderkent: ah, right
11:28Anderkentsandbags: the ns macro quotes symbols for you, so (ns (:require [foo.bar :as zip])) works.
11:28Anderkentbut if you try ##(require non.quoted.symbol)
11:28lazybotjava.lang.ClassNotFoundException: non.quoted.symbol
11:28Anderkentit will not work.
11:28futilewell of *course* writing my parser was so hard, i forgot to split it into a tokenize phase and parse phase
11:28Anderkent##(require clojure.java.io)
11:28lazybotjava.lang.ClassNotFoundException: clojure.java.io
11:28sandbagsah, you're using (require ...) not (ns ... (require ...)) i see
11:28Anderkent##(require 'clojure.java.io)
11:28lazybot⇒ nil
11:28Anderkentyep
11:28futilethats super functional, too. how could i be so silly.
11:28sandbagsI am finding require to be the bane of my existence at the moment
11:29noncomgfredericks: thanks for the reference! seems like that presentation will be very informative for me
11:29sandbagsi have to use it often but I cannot, yet, internalise the rules for writing it properly
11:29Anderkentsandbags: you should use :require within ns form. And you rarely should have a non-ns require in your code
11:29sandbagsi did smile when i watched Chas Emerick's talk about clojure issues
11:29Anderkentit only really comes up in the repl
11:30sandbagsAnderkent: i meant "ns require" rather than the require function
11:30noncomsandbag: what were the issues?
11:30sandbagsmaybe just my brain getting old
11:30sandbagsnoncom: i just find it hard to remember the rules for writing a require correclty
11:30sandbagsand, almost every time, have to refer back to a previous time ive done it or one of my books
11:30Anderkentright. you'll learn it eventually, but in general you only need (ns (:require [full.lib.name :as alias] ...))
11:31noncomsandbags: there are "two different" require, :require in the ns form and (require)
11:31Anderkentall the other stuff like :refer is optional :)
11:31hhenkelAnyone around who can explain why the string "${part2.test2.1}" get replaced with "TESTTEST" using (clojure.string/replace % #".*" "TEST") ?
11:31sandbagsi'm better than i was, but it's just the thing i hit *every* time i am writing code
11:31noncomalthough they are the same ultimately
11:31hhenkelHmm, seems like .+ is better....?
11:31sandbagswhat's the difference between (ns (:require ...)) and (ns (require ...)) btw?
11:31sandbagsi find i am using them interchangably
11:32noncomfutile: what is that parser you're talking about?
11:32futilea parser
11:32futilenoncom: im pissing everyone off by writing my own Clojure parser in Clojure
11:32Anderkenthhenkel: it does seem like a bug.
11:32futileim also using my own testing lib to do it
11:32ToxicFroghhenkel: .* is zero or more of any character. .+ is one or more. The .* might be matching the empty string at the start or end.
11:32noncomsandbags: (:require) is simply a parameter to ns macro, it is not a function call
11:32noncom(require) is a function call
11:33ToxicFrogI've run into similar issues with java's regex library returning spurious empty string matches.
11:33clgvsandbags: you should be using (:require ...) within `ns`
11:33sandbagsclgv: ok, i've no idea quite where I got the (ns (require ...)) pattern from, presumably misreading something
11:33sandbagsthanks guys
11:33noncomnoncom: as (ns) is a macro, the list (:require [stuff :as s]) does not get parsed until it is pulled apart inside (ns)
11:33Anderkentsandbags: it should be (:require) not require :)
11:34noncom(ns (require)) is definitely not what you want, yeah
11:34sandbagsUnderstood :)
11:34sandbagsunfortunately it seems to work (for some value of work involving not raising any errors and doing some kind of require)
11:35noncomfutile: cool! i think that everybody should welcome Clojure parser in Clojure?
11:35sandbagsso it wasn't obvious IWDIW
11:35Anderkenthhenkel: ##(.replaceAll "a" ".*" "FOO")
11:35lazybot⇒ "FOOFOO"
11:35Anderkentso I guess it's a java thing
11:35futilenoncom: they say i should use instaparse or something that already exists
11:35Anderkentbasically the .* matches twice - first for the entire string, then the empty string
11:35futilenoncom: which generally is good advice, but not when the goal is to learn how to write a parser
11:35xeqifutile: you should write your own monadic parser combinator library
11:35futileahhhh!!!!
11:36sandbagsxeqi: hand him a big smelly yakk and a razor why don't you!
11:36arcatanyou should write your own applicative parser combinator library
11:36xeqifine fine, you can stick with an applicative functors .... blah
11:37hhenkelAnderkent: yeah, seems like you're right.
11:37sandbagshrmm.. i can't seem to google this up: I'm running a lein new template app in LightTable... does the process have some concept of what folder it comes from?
11:37futilexeqi: Be that word our sign of parting, nerd or fiend!
11:37noncomi think those are good advices. btw i saw good material on how to write them. for sure i seen much on the topic but for scala
11:37sandbagsso that I can locate a file in the project root folder
11:37futilexeqi: Leave no parenthesis as a token of that lie thy soul hath spoken!
11:38noncomsandbags: try (System/getProperty "user.dir")
11:38technomancyhttp://timberglund.com/blog/2012/08/03/the-maven/
11:38sandbagsnoncom: nice, thanks
11:38technomancyfutile: ^
11:38futiletechnomancy: oh it has a video too??
11:38lazybotfutile: What are you, crazy? Of course not!
11:39technomancyit is. a masterpiece.
11:40futileheh wow
11:40futile"Leave my project's build unbroken!—quit my central source code store!"
11:41futileshoulda said "quit my DVCS store"
11:43sandbagshrmm... am i missing a function for appending to file paths? or (it's been a long time since I did any Java) is this because the JVM abstracts all path separators to "/" so you can just use (str ...) ?
11:44sandbags(and literal "/"'s i mean)
11:44Anderkentsandbags: java.nio.file.Path?
11:45futileso um, i really think my testing lib has advantages over the existing options. is that grounds enough to ANN it on the mailing list?
11:45Anderkentyeah, it's not like anyone reads it
11:45Anderkent;P
11:45noncomfutile: try and see! it's free :D
11:46noncomsandbags: i use (str) to concat strings
11:46futilei guess im concerned because ive announced 2 other testing libs already, to a loud negative critical reaction
11:46sandbagsnoncom: ta
11:47Anderkentwell, we can't promise you'll have a positive reaction... But the problem is probably not in the announcing, but rather in something inherent to the lib
11:47noncomfutile: well, maybe it is worth to have someone test your libs prior to announcement then
11:48noncomi too had that sloppy feeling posting an announcement recently
11:48futileAnderkent: the first time the problem was that the lib was kind of a rude (and stupid) plan, of trying to unify all the testing libs with one backend.
11:48muhooi am deeply suspicious of any "unifying" effort
11:48futilethe second time, the problem was that i had already announced the first one, so people were already not so fond of my releasing a testing lib.
11:48muhoowithout even reading the details of what it's trying to unify.
11:49sandbagsfutile: perhaps, as an alternative strategy, see if someone else can prove your testing library on their project and do a co-announcement?
11:49futilesandbags: thats a good idea
11:50dnolensquidz: I fixed the set bug from yesterday
11:50noncomsandbags: also it is worth putting "/" in (str prefix "/" my-path) for safety, since "folder//folder2" is treated ok, what you cant say of "folderfolder2"
11:50futileEven if nobody else uses it but me, I'll be happy with it. And that's why I think I should consider announcing it.
11:50sandbagsnoncom: yep
11:51noncomfutile: i think that whatever comes up, it is for your benifit
11:51futileOoooh, I know why I can't announce this comfortably... it's because the main reasons I like it are sharply contrasted with the competition (by design).
11:52noncomyou mean it is different from the peers?
11:53futileFor example, you don't write tests at the top-level of a file (unlike in Expectations), and I like the assertion style better than Midje's or Speclj's.
11:53futilenoncom: no, I mean the reasons I like it are because it does things differently than peers
11:54futileAnd that makes me a huge asshat.
11:55noncomfutile: well, when i come into such a position, i write a short document which outlines and describes all the benifits
11:55sandbagsso it seems like i am still struggling with damn requires
11:56noncomthen read it several times
11:56noncomand think if i can present the outline points as a win
11:56noncomthen, if i can manage tht, usually people react good
11:56noncomsandbags: whatsup?
11:56futileI think "referential transparency" might be the shortest way of describing why I wanted it in the first place.
11:57arohnerfutile: link to the lib(s)?
11:57sandbagssomething about the moving parts between what you put in project.clj, what you (ns (:require ...)) in your own code, the lack of error trapping in how project.clj is parsed, the issue of getting the right version numbers, and LightTable not necessarily reporting whatever problems do get trapped properly
11:57futilearohner: https://github.com/sdegutis/nevermore
11:57futileBut I gotta rename it.
12:00noncomsandbags: i find lighttable not suitable for me yet. it is a little unresponsive yet. as for moving parts... idk, you do not have to move anything between project.clj and (ns)... what are you doing?
12:00sandbagsi am sure this probably all becomes subconscious at some point
12:00sandbagsbut as a beginner it has the feeling of being a huge piece of grit in my eye
12:00sandbagsoften making me feel functionally illiterate
12:01sandbagsnoncom: i mean how i put "org.clojure/data.csv" in project.clj but I require clojure.data.csv
12:01sandbagsand how i can be looking at the API docs saying it's v1.3 but v1.3 isn't actually released so it won't load
12:01noncomheh
12:02sandbagsand how if i mess up editing my project.clj so that i end up with [[lib1 "ver" lib2 "ver"]] instead of [[lib1 "ver"][Lib2 "ver"]] it will just silently fail
12:02noncomwell, there is no direct relation between whaat you put in project.clj and what you put in ns. don't look for parallels there. names ofcourse match, but technically there is no conenction
12:02sandbagsnoncom: this is my point
12:03noncomyeah all that was happening to me too
12:03sandbagsright now most of my problems with bootstrapping clojure is not learning to "Think functional, you cannot think objects and translate" but "Why the fuck won't this library require now?"
12:04sandbagslike i say, i presume at some point i'll just internalise all the mucking about and will no longer notice it any more
12:04sandbagsbut it seems like a less than ideal setup right now
12:04noncomif i use (defmacro m [x] '(+ 1 ~x)) how do i make it to resolve x as the param?
12:04sandbagsof course i suspect that all the people who could sand this down have long since stopped noticing and are working on more interesting problems :)
12:05noncomsandbags: right. i noticed that phenomenon to be widely spread over ppl
12:05clgvnoncom: unquote unly works with backtick (defmacro m [x] `(+ 1 ~x))
12:05clgv*only
12:05noncomclgv: so no way?
12:05futilesandbags: I haven't run into that issue.
12:06sandbagsas to LightTable it's for sure still very much a work in progress but as someone who has abandoned all hope of learning emacs (even if my RSI didn't make it a non-starter) i am finding it a generally very productive environment to work in
12:06clgvnoncom: see the example above. that work
12:06clgvsandbags: did you try eclipse+counterclockwise?
12:06sandbagsclgv: no
12:06noncomclgv: but i cant use backtick because it will incorrectly resolve (ns boo) to (ns current-ns/boo) :(
12:06clgvsandbags: you should
12:06futilesandbags: I've also found that paredit helps me avoid a lot of those kind of pitfalls, because it balances parens for me and makes my code structure obvious.
12:06noncomsandbags: i use ccw, give it a try
12:07clgvnoncom: what exatly do you want to do
12:07sandbagsfutile: i am hoping for paredit in a future version of LT, it looks amazing
12:07futilesandbags: but at the same time, I sympathize that emacs is too painful for someone who just wants to write Clojure, that's why I'm writing my own IDE now.
12:07sandbagsclgv: i may have been too scarred by use of Eclipse in a past life
12:07clgvccw has most of paredit as well ;)
12:08sandbagsi no longer remember anything about it, i just feel a deep pain somewhere around my kidneys when I read its name
12:09Anderkenteclipse invariably is a huge pain, but still better for clojure than intellij. If you're not willing to take the vim/emacs plunge, I guess it's the best option
12:09sandbagsI often use Vim but never managed to get a working Vim+Clojure setup
12:09noncomclgv: https://www.refheap.com/18316
12:10sandbagsi've given up trying to learn emacs... 3 attempts is enough (even if my RSI makes it not a great choice)
12:10Anderkentnoncom: that's the correct resolution
12:10sandbagsother than bits of paraedit what would CCW give me that you can't live without?
12:10sandbagswhat's the main selling point?
12:10noncomAnderkent: yes, sorry, it is corerect, but not what i need
12:10Anderkentif you want to strip out the namespace then you need to do `(+ 1 ~@'x)
12:11Anderkenteh wait that's not right
12:11clgvsandbags: what do you use right now?
12:11sandbagsi'd like paredit sure but otherwise, barring the Codemirror versino of Vim isn't complete, i'm not finding myself missing that much in LightTable
12:11noncomsandbags: ccw is heaven
12:12sandbagswell i guess i should probably give it a try
12:12sandbagsdoes it have a debugger?
12:12noncomwhat is debugger?
12:12sandbagsLT is making some steps through it's watches
12:12sandbagsbut i would, occasionally, like to be able to single-step
12:12sandbagsalthough i have no idea how that would work with clojure code
12:12sandbagswhere so much can be happening in "a line"
12:12noncomi do not know, i never use that kind of debug
12:12clgvnoncom: does `x` contain 'boo at compile time?
12:13sandbagsah the joys of starbucks wi-fi and 200mb downloads
12:13noncomclgv: well, i am not sure...
12:14Anderkentnoncom: what exactly are you trying to do
12:14clgvnoncom: that is a problem. with macros you always have to now or specify what is known at compile time and what shall be done at compile time
12:15clgvnoncom: given an example macro call and the desired expansion of the macro call
12:16squidzdnolen: awesome. When do you think I will be able to use it?
12:16noncomwell, you see, that macros, `z` in the refheap post is called from a string that is passed through (eval (read-string s)) first
12:16Anderkenton runtime or compile time?
12:16noncomthat (eval (readstring s)) happens inside the namespace where z is defined
12:17noncomAnderkent: runtime... :( ?
12:17Anderkentright, so you're calling z like (z evalled-string), not (z {:literal :map})
12:17noncomyes
12:17Anderkentand you want to extract a symbol from evalled string on runtime and call ns on it
12:17Anderkentwhy is it a macro?
12:18Anderkentwhy not just (defn z [dict] (ns (:param dict))) ?
12:18noncomhmmm...
12:18clgvnoncom: the use of `eval` there probably adds to your confusion ;)
12:18noncomclgv: sure :)
12:19noncomwell, really.. why is this macro...
12:19clgvnoncom: cant you make a minimal viable gist that should run if the macro was implemented correctly?
12:19noncommust defn be better
12:20sandbagsokay Java interop isn't so hideous after all
12:20noncomclgv: well, idk, that refheap contained all the idea i think, except the eval. a map is read from the string and a namespace is created from one of its params...
12:20Anderkentnoncom: as I said. Just make it a function. Trying to force it to be a macro for no reason is just additional pain
12:21Anderkentsandbags: yeah it's pretty convenient. I find myself firing up clojure repl just to explore java libs etc.
12:21Anderkenteasier than trying to write java :P
12:21sandbagswell i've not written any Java since about 2005 so i'd have to agree with you there
12:21sandbagsalthough i am somewhat surprised more of the IO stuff isn't wrapped
12:22sandbagsi mean, it's not so hideous to write (.exists (io/file "path")) but...
12:22noncomthat puzzled me too
12:22noncomwhy so?
12:23Anderkentyeah, lack of nice wrappers for io/nio is slightly painful
12:23Anderkentbut i guess it's mostly because it's tedius work to create them
12:23sandbagsi guess, to be fair
12:23Anderkentclojure.java.io is already pretty nice :)
12:23sandbagsi'm really complaining about writing ".exists" rather than "exists?"
12:24gfrederickssandbags: (-> "path" io/file .exists)
12:24Anderkentsomething like file/exists? rather than exists?, probably :P
12:24futileok, renamed my testing lib
12:24clgvnoncom: sorry cant help you then. usually you describe a macro as follows. example call (when-let [x (do-sth)] (inc x) expansion: (let [x (do-sth)] (when x (inc x))) [<--- not the expansion of clojure.core/when-let ;) ]
12:24futileno more trying to steal technomancy's naming approach
12:24sandbagsgfredericks: yes that's quite nice ... still haven't quite internalized the -> and ->> macros yet
12:24clgvnoncom: given that information it is much much easier to help
12:24gfrederickssandbags: once you do they become indispensible
12:24shaungilchristsandbags: this was just posted on the mailing list http://www.youtube.com/watch?v=qxE5wDbt964
12:25sandbagsthanks
12:25noncomclgv: you mean the real context of use? but it is the context. i just ommited reading the string from the file and thats it... i am experimenting with creating namespaces through eval
12:25Anderkentit's a slippery slope. You start with -> and ->>, couple weeks till <<- and -<>, and two months later you find yourself with -<><:p and -!> all over the place!
12:26Anderkentnoncom: it's less about the context and more about the purpose
12:26Anderkentthere's nothing that requires dynamically created namespace to be done within a macro. (defn new-ns [config] (ns (:ns-sym config)) (def k 1)) does exactly what you want, as far as I can tell
12:27sandbagsthis is the kind of thing i mean ... Eclipse "Help > Install New Software" because I always look for actions like that in a bloody help menu
12:27clgvnoncom: you provide a macro implementation try and nothing more..
12:27Anderkentsandbags: yes. Eclipse is horrible in that way.
12:27dnolensquidz: probably next week some time, there a few more patches I would like to get in.
12:27sandbagsclojurians do seem to be on a sigil bender lately
12:27Anderkentsandbags: wait until you try to unisntall some plugin. The only way I found to do it is to go help -> install new software -> find the 'what is already installed?' link -> proceed to do actual uninstal
12:27sandbagsat least that's my perception as someone reasonably new to the platform
12:28squidzdnolen: cool thanks for the quick work
12:28noncomoh there was a long talk here recently, i believe on monday.. on why i do this. i do a research project on linguistics where i also research computer languages.. i research self-referencing properties of languages.. as for why i went the macro way.. probably coz im clojure noob :)
12:29sandbagsmacro's are enticing because they're one of the reasons you're there in the first place
12:29noncomno-no, eclipse is beautiful that way! see, you could be installing the plugins manually, by copying jars and writing property files, but Eclipse is there to HELP you install new software
12:29sandbagsbut as with many people i've taught Ruby... you have to check your desire for massively inappropriate metaprogramming
12:30Anderkentmacros bring complexity, if you can do something with a function you shuold always choose that
12:30dnolensandbags: wrapping Java piecemeal is a futile task, CLJS same problem because the enormity of the DOM, generally not worth it unless you're adding real value ie some real abstraction beyond wrappers.
12:30Anderkentonly when there's significant benefit shuold you consider writing a macro
12:30clgvsandbags: in clojure dev I hardly use any eclipse menu ;)
12:31sandbagsdnolen: yeah on reflection i am bound to agree with you
12:31sandbagsit was kind of a knee-jerk reaction
12:31sandbagsoh god i am not sure i can use Eclipse
12:32sandbagsthis is bringing back horrible nightmarish familiarity
12:32noncomme too, i just have the editor, the project tree and the repl
12:32sandbagsof software designed by people who should clearly should have nothing to do with the design of software
12:32sandbagsindeed who should be actively disbarred from the profession
12:32Anderkentsandbags: c'mon, i bet it didnt even hang on you yet
12:33rasmustoAnderkent: it's not the software hanging that he's worried about
12:33sandbagsit's trying its best
12:33noncomdnolen: can a robot do that? (wrapping i mean)
12:34Anderkentyou could generate the bindings that mirror classes one to one, but what's the point
12:34Anderkentit'd only make sense to wrap stuff if you improve the api
12:34sandbags"Problem occurred. Creation problems. Invalid project description."
12:34sandbagsthere is no field for project description
12:34dnolennoncom: think about the differences between hosts, it really is pointless - file handling in Java is sync, file handling in Node is not.
12:35dnolennoncom: these sorts of things better handled in well thought out libraries
12:35dnolennoncom: with specific goals
12:35Anderkentsandbags: what kind of project are you importing? mvn or lein?
12:35sandbagsi am trying to create one
12:35noncomyeah, right..
12:35Anderkentdon't do that. Create the project on filesystem, then import into eclipse
12:35sandbagsof course! i should have realised :)
12:35Anderkenti mean I guess ccw probably gives you some kind of creator
12:35Anderkentbut why learn all that
12:36noncomAnderkent: I can say that creating clojure projects with ccw works for me now..
12:36noncomthere was a trouble with the creator in past versions
12:36sandbagsoh wait... this "workspace" business.. does this need to be a folder that Eclipse can own?
12:36noncomyes
12:36Anderkentsandbags: yes. But your projects can live outside the workspace
12:36noncom:)
12:37AnderkentI just put them in ~/.eclipse/workspaces/XXX
12:37sandbagsi am not sure i can use software that i am going to actively hate this much, even if it does have paredit
12:37Anderkenttreat a workspace as a config set
12:37gfredericksbbloom: I am curious about your "only extend protocol if you own the protocol or the type" guideline
12:37gfredericksin particular this one case I am handling
12:37gfredericksand what you think is wrong with it
12:38sandbags"No projects are found to import"
12:38Anderkentsandbags: did you pick the right type? (clojure/leiningen project I assume)
12:38sandbagsis there some CCW specific import?
12:39Anderkentyes, it will be under clojure
12:39sandbagsi don't seem to have Clojure under the import tree
12:39Anderkentdo you have ccw installed? :P
12:39sandbagsapparently
12:39Anderkentlemme fire up eclipse
12:39Anderkent(back in 10 mins)
12:40noncomsandbags: first, create empty project by New->General->Empty project, specify its folder as the folder of the proj you just created with lein. Right click on it and Configuration -> turn into clojure project..
12:40noncomor turn into lein prject.. i dont remember
12:40Anderkentyuck no don't do that
12:40Anderkenteclipse will do stupid stuff to your filesystem
12:40Anderkentlike create ~/bin or w/e
12:40sandbagsi definitely have CCW as I have File>New>Clojure Project
12:40clojurebotexcusez-moi
12:40noncombut it was the official instruction
12:40sandbagswell perhaps i shouldn't sound so definitive
12:41sandbagswho knows? maybe i have half of CCW
12:41sandbagsand it's severed head is wandering around someone in the upper regions of memory
12:42Anderkenthm, you're right that it doesn't have import
12:42Anderkentthat's weird
12:43noncomAnderkent: if i do "(defn z [dict] (ns (:param dict)))" as you adviced, it gives "ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol"
12:43noncomi believe it treats (:params dict) as a list
12:43noncomcoz it quotes it..
12:43noncom?
12:43Anderkentah yes
12:43sandbagswell this is great, i have now created a new Clojure project
12:43sandbagsand... where the hell is it?
12:43futileha
12:43noncomsandbags: is it in the file explorer?
12:43sandbagsoh i see, i need the workbench
12:43noncomof the eclipse i mean
12:44sandbagshow is this thing not better? this seems like exactly the experience i had last time i tried Eclipse
12:44sandbagshow can almost 10 years not improve a thing AT ALL?
12:44sandbagsthat or it wither and die
12:44technomancyten years ago it didn't support clojure =)
12:44sandbagsit supposes that people are using this piece of shit and living with it
12:45noncomsandbags: i believe that most of your current feelings are induced by the destructive imprint from the past
12:45sandbagsand how is it SO FUCKINGGGGGGGGG SLOWWWWWWWWWWWWWWW
12:45sandbagsi am on a 1.7GHz i7 with 8GB of RAM and an SSD, it shouldn't take several seconds to open a file containing 5 lines of text
12:45Anderkentit's not slow, your machine is slow! At least you have the minimum 16GB ram right?
12:45sandbagsah well, there we go
12:45Anderkentah, 8gb ram is your problem
12:45noncomahah
12:45Anderkentyou're in java land
12:45sandbagsi'll try it on the Mac Pro later
12:46technomancyed doesn't waste space on my timex sinclair you guys.
12:46opqdonutjust use emacs and nrepl
12:46sandbagsnoncom: you could well be right
12:46sandbagsopqdonut: non e possiblé
12:46sandbagsbut i have to say i am feeling a lot better about LightTable's shortcomings right about now :)
12:46technomancysandbags: you've done the obvious stuff like a split keyboard and moving ctrl to the right of the A key, right?
12:46Anderkentnoncom: now htat I think about it, it might well be impossible to do what you want without something like eval
12:47technomancy(re: rsi)
12:47sandbagstechnomancy: yeah i have caps lock mapped to ^ as a regular habit
12:47sandbagstechnomancy: i just can't get along with emacs
12:47noncomAnderkent: err... what would be the way with eval?
12:47technomancyjust making sure
12:47sandbagsi've tried several times
12:47sandbagstechnomancy: thx :)
12:48Anderkentnoncom: (defn redefine-ns [dict] (eval `(ns ~(:param dict))))
12:48noncomohoh
12:48opqdonutinstead of eval you can always just do what ns expands to
12:49Anderkenttechnomancy: to the *right* of a key?
12:49Anderkenti guess you don't like your s's
12:49Anderkentsandbags: just use vim!
12:49Anderkent:P
12:49sandbagsAnderkent: i do!
12:49sandbagswell, for the most part
12:49technomancyAnderkent: derp
12:49pbostromnoncom: (defn z [dict] (let [sym (:param dict)] (ns sym)))
12:49rasmustosandbags: have you tried vim-fireplace?
12:50sandbagsrasmusto: i have not
12:50Anderkentpbostrom: that won't work, (ns sym) will declare namespace claled sym
12:50Anderkentfireplace is ok
12:50Anderkentyou still need to ctrl-z to a real repl from time to time
12:50rasmustosandbags: it's worth a shot, I can't speak to it vs eclipse though
12:50Anderkentbut that's cool
12:50Anderkentsandbags: also vim-paredit
12:50sandbagsi am already two steps from deleting eclipse again
12:50Anderkentmust have
12:50opqdonutnoncom: I'm not sure what you're trying to do, but this might help: https://gist.github.com/opqdonut/6439400
12:50pbostromdoh
12:50rasmustoAnderkent: real repls are overrated
12:51sandbagsi can't imagine what it can do that would be worth living in such an application
12:51Anderkentsandbags: me I was looking to switching to evilmacs
12:51rasmustosandbags: vim-sexp is a paredit-lite, if you like doing more vimmish editing
12:51sandbagsand i think i've caught it before i fall into Stockholm syndrome
12:51Anderkentbut reconfiguring all the bindings for nrepl-el etc to work with my ingrained vim motions is a real pain
12:51noncomthanks to you who have proposed solutions, i am currently inspecting them..
12:51Anderkentand evil doesn't work with paredit
12:52Anderkentwhich is a huge pain
12:52rasmustoAnderkent: the automatic insertion stuff works fine, not so much the movement commands. But there's definitely a lot of overlap
12:52Anderkent(dd etc. unbalance parens)
12:53Anderkenti wish i knew how to get YouCompleteMe to work with fireplace/paredit though :(
12:53Anderkentthen I'd be happy in vimland
12:53futileDoes Clojure have something like C's enum?
12:53noncomfutile: in which sense?
12:54rasmustoAnderkent: <c-x><c-o> isn't good enough?
12:54futileGiving names to auto-incrementing numbers.
12:54Anderkentrasmusto: no, I like to have fuzzy completition all the time, without having to prompt for them
12:54futileI could enumerate through an indexed list of names and do (def) but that feels a bit odd.
12:54rasmustoAnderkent: ah, ok. Have you used autocomplpop?
12:55rasmusto(I love typing that btw)
12:55Anderkentno. I tried YouCompleteMe, which looks similar except it's not written in viml and 3 years old
12:55Anderkentbut it doesn't quite work
12:55noncomfutile: idk meybe there is a lib.. but you could easily write a code for that.. create a {} where name is a key and number is the valie
12:56futilenoncom: so "no"?
12:56futileok
12:56futilethanks
12:56Anderkentfutile: the fact that enums have numbers in java is an implementation detail and you shouldn't really have to use that
12:56rasmustoAnderkent: fireplace handles setting up omnicomplete to work with nrepl, and autocomplpop just makes autocomplete trigger while you're typing
12:56futileOkay better question:
12:56Anderkentrasmusto: right, YouCompleteMe does something similar except it also uses its own identifier-based completion system
12:57futileIs there a way in Clojure to create a bunch of unique-per-process constants?
12:57Anderkentwhich is cool in theory but doesnt seem to work with clojures omnifunc
12:57futileI suppose I could just do (def foobar) and take #'foobar, right?
12:57Anderkentfutile: process or thread?
12:57rasmustoAnderkent: k, that was my impression. You should try out fireplace + <c-x><c-o> (w/ autocomplpop maybe). It works well from my experience
12:57gfredericks(defmacro C-enum [syms] (cons 'do (map-indexed (fn [i sym] `(def ~sym ~i)) syms)))
12:57futileAnderkent: I only mean I don't need it to be persisted between different times of running my app.
12:58technomancyfutile: gensym
12:58futileAnderkent: It should be the same on all threads.
12:58Anderkentyeah gensym sounds right
12:58gfredericksfutile: ^ how's about that macro?
12:58futiletechnomancy: But then it becomes a string. Isn't that inefficient to compare two strings?
12:58futilegfredericks: hmm
12:58Anderkentgensym gives a symbol, symbols are interned
12:58technomancy,(gensym)
12:58clojurebotG__31
12:58Anderkentsymbol comparison is reference equality
12:58futileOh nice! gensym it is then.
12:59Anderkentjust dont use prefixes
12:59futileThis should work excellently for representing different token types.
12:59TimMcfutile: Why not keywords?
12:59futileTimMc: I want compile-time errors.
13:00TimMcThat's what I was afraid of.
13:00TimMc"Giving names to auto-incrementing numbers." is not "I want compile-time errors."
13:00futileWait, I vaguely remember some email thread a month ago about how keywords are interned but symbols aren't, on account of metadata...
13:01futileTimMc: sorry, I'll work on asking better questions
13:01TimMcSymbols are not interned, but they use interned strings.
13:01futileah
13:01rickmodeleiningen question: Is there a way to disable the AOT that's needed for a main when launching a REPL?
13:01futileSo the interned strings are ref-compared then?
13:01futileworks for me
13:01Anderkentfutile: well, they're .equal compared but .equal checks for reference equality first
13:01AnderkentI'd assume
13:03Anderkent,(let [target (gensym "foo1")] (loop [attempt (gensym "foo")] (if (= target attempt) :broke-it (recur (gensym "foo")))))
13:03clojurebot:broke-it
13:04Anderkentjust saying D
13:04pbostromnoncom: one more attempt (defmacro z [dict] (let [s (:param dict)] `(ns ~s)))
13:04clgvrickmode: yes search for lein-otf
13:04Anderkentpbostrom: that only works if dict is a literal map
13:05rickmodeThe main and AOT config for my project is only useful with an uberjar (which seems like the normal case), so I'd like to avoid it at the REPL
13:06rickmodeclgv: ok, I'll check that out
13:06clgvrickmode: the author of it is online right now (TimMc) ;)
13:07noncomyeah, trying, still exploring..
13:09noncommimicking macroexpandlooks the closest now..., but `(ns ~s) may also work..
13:09clojurebotI don't understand.
13:10clgvnoncom: you can try those in repl as well ##(let [s 'bla] `(ns ~s))
13:10lazybot⇒ (clojure.core/ns bla)
13:14solussdwhy cant I put metadata on a list?
13:15clgvsolussd: you can ##(let [l (with-meta '(1 2 3) {:awesome true})] (meta l))
13:15lazybot⇒ {:awesome true}
13:15rhg^20.it's a jav interface
13:15rhg^2i forget which
13:16solussdbut I couldnt ##(let [l ^{:type :thing} (list 1 2 3)] (meta l))
13:16lazybot⇒ nil
13:16rhg^2java objects don't usually have it tho
13:16noncomi have succeeded with the way of expanding ns to its macroexpand. now i will also try the `(ns ~s) way..
13:16clgvsolussd: there is a difference between compile time meta data and runtime metadata
13:16solussdack- right.. i'm being stupid
13:16Anderkentsolussd: ^{} puts metadata on the (list 1 2 3) list for the compiler to see
13:16clgvsolussd: ^{...} is compile time meta data
13:17solussdthanks!
13:35sandbagsany feedback about this code i've written https://gist.github.com/mmower/b755a0b6f88292d9cec2 (it's pretty short)... looking mainly for comments on style/good practice
13:37sandbagsthe one thing i certainly noticed was that i'm using (get-in ...) to create a default empty vector for a key if it's not been seen before
13:37mdrogalissandbags: It's a little long and does a few different things, but mostly looks good to me :)
13:37sandbagsand then (assoc-in'ing) with that vector conj'd later and i wondered if it was possible to combine the two
13:37justin_smithsandbags: a loop where you keep grabbing the rest can be trivially made into a more idiomatic reduce
13:38sandbagsmdrogalis: thanks... how would you see it being split up?
13:38justin_smiththe first rows / rest rows becomes implicit with a reduce, you just get the next row on each call to the reducing function
13:38sandbagsjustin_smith: hrmm.. yes.. i'll think about that thanks
13:38kawHey, does anyone know what this error from attempting to use clojurecheck might be caused by? Exception in thread "main" java.lang.UnsupportedOperationException: Cannot recur across try, compiling:(clojurecheck/core.clj:311:17)
13:38mdrogalissandbags: Not sure, just have time for a quick glance.
13:38justin_smithalso, when you are using reduce, you can talk out the doall (since reduce is not lazy)
13:39sandbagsmdrogalis: i guess what i am asking is whether you'd extract the inner part that processes the rows into a function
13:39sandbagsat which point i guess you're pretty close to the reduce
13:39kawFollowed by around 100 lines of stack trace mostly from within clojure.lang, I don't know if any part of that is interesting?
13:39sandbagssince it pulls the op out of the plumbing
13:39sandbagsjustin_smith: ah, that's definitely a benefit
13:40justin_smithI say take the fn out of the plumbing if you would ever use it in another context, otherwise make in an anonymous fn inside the reduce call
13:40sandbagsjustin_smith: yep i think that's what i will try, thanks again
13:41mdrogalissandbags: Yes.
13:42kawI mean, I can see it's an error about using recur across try, but I assume clojurecheck worked at some point, so might it be something like a version issue, or a mistake in how I'm using it?
13:42sandbagsmdrogalis: ta
13:45kawOh, it looks like that was disallowed in 1.3, so I guess clojurecheck hasn't been updated to work with 1.3
13:45kawIs there any quickcheck-like for Clojure that's up-to-date?
13:47s4muelkaw: https://github.com/reiddraper/simple-check
13:50kaws4muel: Aha, I'll check that out, thanks
13:53callenare there any semi-authoritative benchmarks on core.async that I should be aware of?
13:53callenAll I can find is the thread-ring'ish benchmark dnolen did.
13:59danlentzis there a "top" type in clojure? i.e. similar to T in CL? (for method dispatch using #'type)
14:00augustlcallen: it's in snapshot so I wouldn't be surprised if there isn't a lot of that around yet
14:00callenaugustl: should I not use it in production? :P
14:00augustlcallen: not sure tbh. If it works it works, I guess. What could possibly go wrong, etc :)
14:01llasramdanlentz: For multimethods you can use :default (or a default value you define your self for the particular multimethod). For protocols and manual reference-based dispatch, in JVM Clojure you can use Object.
14:01danlentzwouldd that be java.lang.Object?
14:02dnolencallen: what type of benchmark specifically are you looking for? at this point I find it highly unlikely to be a bottleneck
14:02danlentzcool tis kindly. :default should do nicely.
14:03callendnolen: I don't know how else to put this, so I'll just say it - I have to do a thesis defense'ish of Clojure, Datomic, and things like core.async. It would be nice if I could demonstrate how incredibly roundabout and backwards it is to (ab)use RabbitMQ in Python as a local backchannel in your processes.
14:03callendnolen: to that end, things like latency and throughput would make the case wrt performance, the case for simplicity might require more de-programming of them.
14:04technomancypython doesn't have a j.u.c queue equivalent?
14:04callentechnomancy: there's a Queue, but it doesn't really behave the way you think.
14:07dnolencallen: oh I can't speak broadly about the perf of Clojure JVM async, I suspect it's very, very good seeing as rhickey reviewed most of that code - most of the recent work tbaldrige and I did was just trying to get things close to the JVM modulo threads.
14:11callendnolen: do I have any reason to be concerned vis a vis using core.async in production?
14:11noncomso alright, the macroexpand way worked fine! the other way that was proposed requires much quoting/unqoting and stuff. i got lost in that, especially when i add more instructions. but i am sure it will work if done correctly. i will explore it some time later
14:12callenobviously it's a permanent rolling snapshot.
14:12callendnolen: API and functional stability being the main thing in mind.
14:21coventryWould it make sense for the (fn) macro to throw an error if the condition-map has keys other than :pre or :post?
14:22muhooaren't :pre and :post just metadata?
14:22muhooand {:pre [()]} is just sugar, IIRC?
14:22callenthat was my understanding as well.
14:23coventrymuhoo, callen: Not necessarily: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L4120 http://clojure.org/special_forms#Special Forms--(fn name? [params* ] condition-map? exprs*)
14:25callenso it's actually yanking them out and mapping assertions across them. nifty.
14:25coventry(I.e., if the body has more than a single map, and the first element is a map, that is taken as the condition-map.)
14:26coventryIn other words, if you had some other map in there by accident, fn would silently eat it.
14:27callennom nom.
14:31dnolencallen: high level api seems relatively stable, the only thing I know of coming down the pipe is read/write only ports
14:31sdegutisWith such smart people in here, I wonder what would happen if you all spent a whole 8 hours working on the same project together. I bet it would be really awesome.
14:42callensdegutis: doesn't work that way.
14:42callensdegutis: you can't put 9 mothers together and get a baby in 1 month.
14:42callensdegutis: but I'm sure the channel collectively appreciates the compliment :)
14:43callendnolen: okay, I'll just take it for granted that given the people involved, it'll be fine. Thanks.
14:44sdegutiscallen: I've only heard of that book, not read it. But that's the example I hear every time it's referenced.
14:46callensdegutis: it's the most clear way to express the thought.
14:46sdegutiscallen: I just see so much collective potential in here, it's exciting to think of how it could all be used.
14:46callenit merits a read.
14:46sdegutiscallen: have you read the book?
14:47callenyes, it's one of the better ones I've read on the abstract nature of software projects.
14:47sdegutisCool, I might have to check it out.
14:49Brand0apparently I'm a moron
14:49sdegutisNope.
14:49sdegutisI don't think anyone in #clojure is capable of being such.
14:50sdegutisThe language has a certain barrier to entry that prevents it.
14:51Brand0lol
14:51shaungilchristsdegutis: I have wondered in the past if there was a well defined spec in which each function has a clearly defined input and output (and perhaps a definition of non-standard lexically available functions) if something like that would be possible
14:52sandbagsjustin_smith: so i followed your advice --> https://gist.github.com/mmower/d170188fcf88d8208ee8
14:52shaungilchristlike to the point each person is working on one function at a time and may have no knowledge of how it fits into the whole scheme til the end
14:52shaungilchristthey just deliver a working function that meets the spec
14:53shaungilchristI think it would work for trivial things where a grand vision is not required e.g. a dr mario clone or something to that effect
14:53sandbagsthe one thing that bothers me now is having to use get-in as well as assoc-in
14:53sandbagsi feel like i want an assoc-in that also takes a default value
14:54sandbagsno
14:54sandbagsthat makes no sense
14:54sdegutisshaungilchrist: as long as the bigger picture is well-defined in advance, I think that would be a really fun and feasible project.
14:55sdegutisshaungilchrist: I mean the architecture and all the details of each function's inter-operation, like you said.
14:55rasmustosandbags: how about update-in?
14:55sandbagsa ha!
14:55sandbagsrasmusto: that is i think exactly what i was after, thanks
14:56rasmustoany time
14:56shaungilchristIt would be called fn-quilt and people would jump into the site and just grab a fn here or a fn there and write them on their lunch breaks contributing to a tapestry beyond their imagination
14:56sdegutisIs it possible to model an entire tree in an immutable fashion, whose deep nodes need to change (mutate) in response to events?
14:57callensdegutis: zippers.
14:57sdegutisThe only way I can think of is by writing some kind of walking function which walks the whole thing, mutates the deep part needs the change, and returns the whole thing, but that seems difficult.
14:57callensdegutis: zippers.
14:57sdegutiscallen: Thanks I'll google it.
14:57sdegutishttp://clojuredocs.org/clojure_core/clojure.zip/zipper
14:58sdegutisThis comes with Clojure?
14:58callensdegutis: yes.
14:58sdegutisSounds like I'm not the first person to have this problem.
14:58callenzippers are important, people really need to become comfortable with them.
14:58sdegutis(Nor second.)
14:58callensdegutis: I've needed zippers at least 3 different times in the last ~9 months and zippers are the basis of more than one templating library in Clojure.
14:59ToxicFrogWhy is using a zipper for this a better choice than associ-in?
14:59sdegutiscallen: The could use some more advertising, I've never heard of them until now. I've seen "zip" namespace in clojuredocs but assumed it was some specialized versions of &&(doc zip)
14:59sdegutis,(doc zip)
14:59clojurebotHuh?
14:59technomancy~zip
14:59clojurebotzip is not necessary in clojure, because map can walk over multiple sequences, acting as a zipWith. For example, (map list '(1 2 3) '(a b c)) yields ((1 a) (2 b) (3 c))
14:59sdegutistechnomancy: yeah that
14:59sandbagsrasmusto: yep, update-in worked a charm thanks again ... now i just have to try and remember about it :)
14:59sdegutisToxicFrog: because I generate the deep-location dynamically
15:00sdegutisToxicFrog: or rather, I find the deep-location dynamically and don't have it up-front.
15:00ToxicFrogAah.
15:00rasmustosandbags: I usually have at least 3 clojure cheatsheet tabs open at any given point
15:00sdegutiscallen: Can you write a blog intro on zippers? I don't know where to start in the 'zip' namesapce.
15:00sandbagsrasmusto: :)
15:00ToxicFrogBecause generating it dynamically is fine as long as you have the whole path ready when you call assoc-in.
15:00ToxicFrog,(inc sdegutis)
15:00clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: sdegutis in this context, compiling:(NO_SOURCE_PATH:0:0)>
15:00ToxicFrog(inc sdegutis)
15:00lazybot⇒ 1
15:01sdegutisWhy?
15:01clojurebotsdegutis: because you can't handle the truth!
15:01sdegutisOh.
15:01callensdegutis: zippers are kind of annoying to learn, and doubly so to teach.
15:02callensdegutis: you might be able to bribe me into writing a blog post on them if you work on something I care about.
15:02sdegutiscallen: I work on nothing to be cared about, and even if I did, I come with no credibility that would make such a project seem feasible.
15:03sdegutiscallen: All I can do is show a working product that people *may* care about, but by that point the deed's already done and it's too late for such a blog post.
15:04callensdegutis: that's my point, you'd have to put aside other things and work on something I care about to win the labor it would take me to write a blog post explaining zippers.
15:04callenlabor-for-labor trade.
15:04sandbagsbut how long would he have to work on it for? :)
15:05callensandbags: that's a matter of negotiation and figuring out which item on my to-do list he wanted to do.
15:05sdegutiscallen: Are you content with your Clojure editor?
15:06callensdegutis: I'm an old-timer Emacs user, what do you think?
15:06sdegutiscallen: Then you won't care about my project. So there's nothing left to do but part ways.
15:08etehtseahttps://gist.github.com/etehtsea/ec7fca0f9539a0e398f7 why concat causes stackoverflow?
15:09callensdegutis: well you're not going to get my labor for free. :P
15:09sdegutiscallen: Then I'll have to read the docs myself. And if I figure it out, I'll probably have to write a blog post about it.
15:11sdegutisActually I might not even need zippers.
15:11callenI've seen a lot of people write code that got them halfway to zippers, wasting a lot of time in the process.
15:12sdegutisConsidering my tree-building phase is actually 2 steps, I'll probably need to rebuild the tree instead of just modifying the node that changed.
15:12sdegutisBut the tree-builder will get called about 10 times per second, so it needs to be efficient and fast. Hmm.
15:14noncomis there a way to save the state of the whole clojure environment?
15:14noncomand then restore it...?
15:15callennoncom: you want smalltalk/CL style images? god help you.
15:15sdegutisnoncom: Why do you want that?
15:16noncomyeah, i guess that kind of thing. i would explore the possibility to clone the environment on multiple computers
15:16noncomso it would be the same one.
15:16nDuffetehtsea: the literal (not Clojure-y, not efficient, but smallest-change) answer is to use (vec (last parts)) instead of just (last parts)
15:16noncomi can imagine doing run-time sync, but what about if i am to rise a new node
15:20nDuffetehtsea: ...you could use (doall last-parts) in the same way.
15:20etehtseanDuff or smth like this (mapcat vec [(first parts) [e] (last parts)])
15:20etehtseanDuff, thanks
15:21augustlnoncom: the closest thing I can think of is to get the environment to where you want it, and fork the processes from that, and use the forked processes for actual work
15:21augustlthat won't store the env to disk of course
15:21noncomideally i would like to transfer it over network :)
15:22augustlshould be possible to model your system so all state is stored as clojure values, which is easy to serialize
15:22noncomright, and the program part can be transfered as sources
15:22augustlthen again, stuff like databases is typically the solution to these kinds of problems :)
15:23noncomyeah
15:26nDuffetehtsea: ...but yeah -- it's not the initial concat that's overflowing the stack, but the attempt to realize the concat-based lazy sequence.
15:38augustlis there any generic library around for doing a immutable data structure that is implemented with periodic merges, rather than the STM's approach of merging immediately? Not sure if my quesiton actually makes any sense.. Mostly thinking of the way datomic keeps a tx log and merges the tx-es into the datomic data structure periodically, for performance.
15:39augustlI've never written any code like that so for all I know there's no generic way to do it anyway :)
15:41bbloomaugustl: such a merge is gonna be pretty data-specific
15:42augustlbbloom: that makes sense
15:43gtrakaugustl sounds a lot like cache coherence, maybe that's a useful way to think about it?
15:44augustlgtrak: I'll look that up, thanks :)
15:44hyPiRionaugustl: You can do it the other way around though. The concurrent hash tries by Bagwell are mutable, but gives you the possibility to take snapshots. So instead of doing periodic merges, you do periodic snapshots.
15:44augustlI like immutability :)
15:44hyPiRionGranted, this only makes sense if you are writing a lot more than you are reading
15:45augustlI see
15:45augustlafaik datomic has no mutable components for achieving its periodic merges. Not that Datomic is a prime example of write scale anyway.
15:48coventryI'd be grateful if someone could look this over before I submit a pull request. It is a patch to core.clj to sanity check fn's condition-map. https://github.com/coventry/clojure/compare/add-fn-condition-map-sanity-checking
15:49dnolencoventry: note you can't submit pull requests
15:50coventryOh. :-)
15:52coventryIs it worth sending the patch to clojure-dev?
15:53coventryOh, here we go. http://clojure.org/patches
15:53mdrogalisCan ask the Clojure-dev mailing list if in doubt.
15:54hyPiRionyou need to sign the CA to post there though, unless that has changed recently
15:54dnolencoventry: you need to send in a CA, open a ticket in a JIRA and attach a patch.
15:55coventryThanks, everyone. Will do.
15:55hyPiRionYou can, however, open a ticket in JIRA without a CA
15:56squidzwhat is the clojurescript type ChunkedCons? it isn't supposed to support next?
15:57squidzI mean is it supposed to support he protocol INext ? I'm not sure what the type is supposed to be
15:58noncomis there a way to know all namespaces that are currently loaded into a clojure system?
15:59dnolensquidz: it doesn't support INext which probably an oversight
15:59squidzokay so it is supposed to support it?
16:01mdrogalisnoncom: ,(doc all-ns)
16:01mdrogalisI dont know how to use clojurebot :(
16:01noncom,(doc all-ns)
16:01clojurebot"([]); Returns a sequence of all namespaces."
16:01dnolensquidz: probably, http://dev.clojure.org/jira/browse/CLJS-585
16:01hyPiRionmdrogalis: ##()
16:01lazybot⇒ ()
16:01mdrogalisAh D:
16:01dnolensquidz: what were you doing where you wanted this?
16:01dnolensquidz: also how are you calling next?
16:01noncom## is the syntax for inline to-be-evals?
16:01dnolensquidz: next directly or through the protocol?
16:02noncom,(all-ns)
16:02clojurebot(#<Namespace clojure.uuid> #<Namespace user> #<Namespace clojure.core> #<Namespace sandbox> #<Namespace clojure.repl> ...)
16:02dnolensquidz: next directly or through the -next protocol fn, rather
16:02noncomcool!
16:03squidzdnolen: here is the error I am getting https://www.refheap.com/18332 that is outputted from google chrome
16:03dobry-denCan anyone point me in the right direction if I have a CLI blog.jar utility that I want people to be able to download and invoke like "blog new blogname". how would i get around invocation like `java -jar blog.jar new blogname`.
16:04dnolensquidz: yes, but what is the code that causes the error?
16:05dobry-denOr I guess does anyone know of a Homebrew package that wraps a .jar that I can look at
16:06squidzdnolen: I still have to try and find a minimal example that reproduces it
16:06squidzthat is not dependent on other libraries etc.
16:07xeqidobry-den: you could create an executable that does the call for you, like a shell script and .exe equivalent
16:09dobry-denxeqi: of course. thanks.
16:09dobry-den`blog` would just be a function that sends commands to an underlying .jar
16:18squidzdnolen: i'm not sure why the ChunkedCons is being created. It is from core.async channel that contains holds json data
16:20dnolensquidz: what else is in the stack trace? something must be calling -next
16:21squidzdnolen: forgot to paste the stack trace here it is https://www.refheap.com/18332
16:22dnolensquidz: what 10953, what's the code there?
16:24coredhello
16:24squidzdnolen: https://www.refheap.com/18332
16:28dnolensquidz: what is the name of the fn that code is in :)
16:28squidzdnolen: core.hash_set
16:37squidzdnolen: if you figure out a fix, can you let me know so that I can use it until it is merged into the next clojruescript version
16:40vmarcinkohello, just a clojure noob question... i finished the books on clojure, and i mostly udnertsnad the syntax, but now i want to find out how to best architect the application. In my (until now OO) apps, I usually distinguish in my mind between command and query methods on my servcie layer. Commands have side-effects. In clojure, or maybe it should gbe general rule, it is good to try to separate side-effects of such
16:40vmarcinko command functions in such way that one should try to have as bigger piece of that function body as pure functions, and then, at the very end, to perform side-effect function, right?
16:41vmarcinkoin other words, body of such command functions should be:
16:42vmarcinkosome-pure-fn1
16:42vmarcinkosome-pure-fn2
16:42vmarcinkosome-pure-fn3
16:42vmarcinkoand then...
16:42dnolensquidz: your bug should go away in next release, hash-set has change
16:42vmarcinkoside-effect-fn
16:42dnolensquidz: still ChunkedCons should probably implement INext to avoid this altogether
16:43squidzdnolen: okay is there anything I can do to get my code working until the next release?
16:44dnolensquidz: what are you passing to set? a large vector?
16:45squidzyes exactly
16:46squidzdnolen: but I it needs to be a set because I use interesection with the results
16:47dnolensquidz: are you using 1859?
16:48squidz1859?
16:48dnolensquidz: what version of ClojureScript
16:49squidzoh i'm not sure, is there a quick way to find out?
16:50dnolensquidz: you should specify it explicitly
16:50dnolensquidz: in :dependencies in project.clj, [org.clojure/clojurescript "0.0-1859"] is what you should be using
16:51dnolensquidz: it would help if you can confirm this issue exists in that version
16:51squidzokay
16:51dnolensquidz: make sure to remove an intermediate compiled artifacts, rm -rf target or whatever
16:52squidzI assume a lein clean lein cljsbuild clean will remove everything
16:52patchworkvmarcinko: Yes in general, I try to separate functions with side effects from pure functions as much as possible, and wait until the last possible moment to impose side effects. Your approach seems sound if you need side effects, but also you could just have all of the pure stuff happening in one function and pass off the result to another function that does side effects
16:53squidzi'm not sure whether I was using an externally built version of clojurescript or maybe a verson provided by lein cljsbuild (if it does that)
16:54vmarcinkopatchwork: but what if I need to have result of some side-effecting function in the middle of some top level business function, so I could continue to do the processing? is it normal then to have this top level fucntion body something like:
16:54vmarcinkosome-pure-fn1
16:54vmarcinkoside-effect-fn1
16:54vmarcinkosome-pure-fn2
16:55vmarcinkofinal-side-effect-fn?
16:55dnolensquidz: probably whatever cljsbuild pulls in, fortunately that behavior is not long for this world
16:55patchworkvmarcinko: Sure, as long as you encapsulate as much as you can in the pure functions
16:55squidzdnolen: seems to have not changed. Is there a way to view the version being used. And will specifying the version in my projects dependencies take precedence over lein cljsbuild
16:56patchworkvmarcinko: Once you are on the business layer there is likely to be a lot of side effects, but you can still design most of your code to be transformations and then execute your side effects with the results of these pure transformations
16:56vmarcinkopatchwork: i know that its good to separate side-effect fns from the pure ones, but my question was more is it good practice to try to pull this side-effecting functions to surface (upper layers) as much a s possible?
16:57patchworkvmarcinko: Yes, it is
16:57dnolensquidz: what you specify takes precedence.
16:57patchworkdelay your side effects as long as possible
16:57vmarcinkook, thanx
16:58squidzdnolen: okay so I specified version 0.0.1859, and lein seems to have downloaded it and be using it, but the problem isn't any different
16:59vmarcinkopatchwork: though i dunno if it goes somewhat against layering principle, because I dunno if top-level business function should care about some side-effects because these side-effects should maybe best be hidden from top-layers, no?
16:59dnolensquidz: ok I can repro
16:59dnolensquidz: I'll try to push another release soon
16:59dnolensquidz: a minimal case is this, (set (map inc (into [] (range 100))))
16:59dnolensquidz: to avoid you need to convert your result into a vector before you call set
17:00squidzah okay, is it the size of the vector that makes a difference
17:01sdegutisIs there a side-effecty variation of (binding) that's thread-local?
17:02dnolensquidz: no, it's the ChunkedSeq/Cons results from calling a seq operation on a vector
17:02dnolenChunkedCons just doesn't implement INext, that's what needs fixing.
17:02squidzdnolen: okay, thank you for the help, converting to a vector before set seems to quickfix for now.
17:05sdegutisOh, looks like (set!) is what I want.
17:19asteveso, I've been fighting Exception in thread "main" java.lang.NoSuchMethodError: clojure.lang.RT.mapUniqueKeys([Ljava/lang/Object;)Lclojure/lang/IPersistentMap; for a few days now
17:19asteveI'm attempting to upgrade a project from 1.2 t .15.1
17:19asteveto 1.5.1*
17:20astevelein deps :tree shows [org.clojure/clojure "1.5.1"]
17:21sandbagshrmm... i'm trying to use hiccup/html passing it a vector of elements i've built up. But it's expecting its arguments to be passed directly, not in a vector ... however html is a macro so I can't use apply. anyone know any tricks for handling this situation?
17:21sdegutisSome of Clojure's features seem like they were invented to make Datomic work, like tagged literals.
17:21sandbagsi.e. it wants (html [:p "foo"] [:p "bar"]) rather than (html [[:p "foo"] [:p "bar"]])
17:21technomancysdegutis: nonsense; every app needs uuid literals
17:22hyPiRionsandbags: You sure about that? I'd think both works just fine
17:22technomancyfor example, I use uuid literals to identify all the factorials I generate in production
17:22hyPiRion*both would work
17:22sandbagshyPiRion: well not 100% but i tried it and got an error about [ some long vector ] not being an element, maybe i did it wrong
17:23sdegutistechnomancy: true but do they need to be stored in EDN?
17:23coventryasteve: What version of clojure is reported by "lein repl" in that project?
17:23riley526sandbags hyPiRion: I remember (html [[:p "asdf"] [:p "qwerty"]]) not working for me either.
17:24hyPiRionriley526: yeah, confirmed that it's not working here either.
17:24astevecoventry: REPL-y 0.1.9 and Clojure 1.5.1
17:24sandbagshyPiRion: https://gist.github.com/mmower/4a5840897b6c0c8f96c5
17:24technomancysdegutis: well technically they don't but the fibonacci ones definitely do
17:25sdegutistouché
17:25sandbagsi guess maybe i could use a macro to do this?
17:25sandbagsusing the splicing quote?
17:25sandbagsis this... a legitimate time to reach for a macro? :)
17:25riley526sandbags: I think I ended up using (into [:base-elem] ...) to work around it
17:26riley526really annoying though
17:26sandbagsriley526: i'm not sure i understand
17:26sandbagsor, rather, i am sure that i don't :)
17:27sandbagsthe problem seems to be that i can't pass a vector at all
17:27sandbagsso i'm not seeing how injecting elements into one gets me further?
17:27coventryasteve: Do you get the same error if you run the code in the repl?
17:27riley526sandbags: In my case, I often wanted to run (html) on a vector of other elements I had compiled, but (html) doesn't take a vector. so I compiled the elements into a parent element instead of a bare vector.
17:28astevecoventry: it's a storm project and I don't fully understand how to run it locally
17:28riley526sandbags: doesn't solve the problem, but it's what I ended up with.
17:29sandbagsok, thx
17:29riley526(html (into [:div] [[:p "abc"] [:p "def"]]))
17:30gfredericks"The reader, and the Clojure data representations, have utility on their own in many of the same contexts one might use XML or JSON etc."
17:30hyPiRionsandbags, riley526: There's a better solution, actually. Try out (html (seq [[:p "asdf"] [:p "qwerty"]]))
17:30coventryasteve: Oh, so "lein repl" is not executing in the context where you're getting the error? Try (core/spit)ing clojure-version to somewhere you can read it, from that context.
17:30hyPiRionI knew it was possible, but didn't know the incantation
17:31riley526hyPiRion: oh snap
17:31riley526well there you go
17:31nopromptriley526, sandbags you could always use a list instead of a vector and that should also work.
17:31sandbagshyPiRion: oh ho ho
17:31sandbagsnice, thank you
17:31noprompt(list [:el "foo"] [:el "bar"])
17:32riley526I'm practically brand new to hiccup and clojure in general, so most of these simple solutions don't come naturally yet.
17:32nopromptnot as nice as a vector though but i think that should work if i remember the source correctly
17:32sandbagshyPiRion's (seq <vec>) seems to work also
17:32coventryasteve: Actually, (clojure-version) (it's a function.
17:32astevecoventry: thanks, doing that now
17:32sandbagswhich allows me to work with vectors and just convert at the end
17:33nopromptoh snap! multi-term! yay, now i (almost) never need to leave emacs.
17:38rurumate_what happens in clojurescript when I define a var with a name that contains a minus sign, like (defn ^:export sudo-make-payment-button [] (alert "Syntax error")) ? The - is special syntax in javascript no?
17:40nopromptrurumate_: the symbol would be rendered as sudo_make_payment_button in javascript.
17:40sandbagsokay this is nice... it's certainly taken me a few hours but i've done some useful work in Clojure this afternoon that I'd normally have done in Ruby. Learned quite a bit, and have some reasonable I think (for my level of experience) code to show for it.
17:40nopromptsandbags: that's how i started. :)
17:41sandbagsit feels good not to be defining methods on object and pretending I have functions :)
17:43nopromptrurumate_: you also notice symbols like create-user! will be rendered as create_user_BANG_ etc.
17:44rurumate_noprompt: yo thanks mate
17:45nopromptrurumate_: yo dawg i gacho back bra' ;)
17:45noprompt:
17:45noprompt:P
17:47nopromptrurumate_: seriously though, it's definitely worth looking at the emitted code in with, say, :optimizations :whitespace.
17:50coventryHmm, there's a whole bunch of special forms mentioned in ##(map (comp name first) (seq clojure.lang.Compiler/specials)) which do not appear in <clojure.org/special_forms>. Glad I found that snippet.
17:50lazybotjava.lang.SecurityException: You tripped the alarm! class clojure.lang.Compiler is bad!
17:51coventry...and no easy way to tell which arguments to them get evaluated and which are special, without reading Compiler.java, for many of them.
17:51parametrizationhowdy all.
17:53callenparametrization: hi
17:54nopromptcallen: hi
17:54callennoprompt: hi
17:56rurumate_sandbags: are you only pretending to have functions?
17:56parametrizationI've just picked up a tiny project at work, done in clojure. Most of my work involves java, javascript, and the occasional shell or perl script. I'm trying to figure out what folks use for development. I don't think I'm going to have the time to learn the EMACS sufficiently, so I'm wondering if anyone uses something other than the EMACS? I'm using lein, if that makes a difference.
17:57nopromptthis looks so awesome http://oldcomputers.net/oldads/80s/apf.jpg
17:57brehautcoventry: two points: i dont thing they are all special forms, just special (eg, i dont think & is a special *form*, but it is special), and some of the special forms are actually implemented with form* names and tehn have macros wrapping them up with all the swanky features we want
17:57sandbagsrurumate_: unless we're arguing over the semantics of a method as a function with an implied self, yes
17:57taliosmourning brehaut
17:57brehauthat talios
17:58brehauts/hat/hey/
17:58nDuffparametrization: editor choice is covered in the annual survey, if you want to get an idea of what folks use.
17:58nDuffparametrization: ...emacs _is_ far and away the home of the best tooling, but it's certainly not your only choice.
17:58nDuffparametrization: http://cemerick.com/2012/08/06/results-of-the-2012-state-of-clojure-survey/
17:58talioside sluts all of you ;)
17:58rurumate_sandbags: I'd rather have functions
17:58parametrizationThanks, I don't know much about this community ATM, I'll click the link and RTFM for a bit, thanks!
17:59brehautcoventry: the docs should probably should mention the deftype stuff however
17:59parametrizationThanks nDuff.
17:59sandbagsrurumate_: apparently so would I since, despite my liking Ruby very much, I am here in Clojureland
18:00rurumate_sandbags: what drove you away from glorious rubyland?
18:00coventrybrehaut: Thanks, good point. I'm trying to make a macro which wraps everything evaluable in the macroexpansion up in a tracing form, so this list is actually more useful to me than the clojure.org/special_forms page. I agree that that page is pretty good for regular clojure use.
18:01rurumate_dont they have functions there?
18:01sandbagsrurumate_: nothing drove me away, i still like Ruby, but I was drawn to clojure as a Lisp i might actually use
18:01sandbagsand by a desire to really understand FP
18:01nopromptparametrization: the clojure community is full of good people. your in a safe place.
18:01sandbagsi've been an OO programmer for longer than i care to remember, maybe i'm feeling the straightjacket was a little too tight
18:02sandbagsat least it is now... we'll see over time
18:02nopromptparametrization: people here are typically very friendly and helpful.
18:02sandbagsif Clojure ever gets its "Rails" and the influx of bodies that come with it that'll be an interesting test of community
18:03parametrizationnoprompt I was just telling my team about the lack of condescension up in here :)
18:03rurumate_sandbags: I heard they write the opening paren after the function name in non-lisp-land..
18:04sandbagsrurumate_: in ruby-land they often do not write the paren at all!
18:05nopromptsandbags: it'd be a shame if that's what it would take to get people to pay more attention to it.
18:05rurumate_I've heard that parens are very rare in pythonland..
18:05coventry"Here's zero bucks, kid. Go hit gnu.org and buy yourself a real development system."
18:05sandbagsnoprompt: that's life
18:05sandbagsnoprompt: gravity is as gravity does
18:06nopromptsandbags: at least it'd be a shame to me. it bums me out when people won't try out a new language unless 90% of the thinking they'd ever have to do is already done for them.
18:06callensandbags: it's already easy to make web apps in Clojure, you don't really need a shake-n-bake framework or discrete culture around such a framework to accomplish the same things.
18:06sandbagsnoprompt: that's not why i think Rails became popular but that's probably off-topic here
18:06callenas a result, people just kinda do their thing.
18:06sandbagscallen: it was already easy to make web apps in Ruby
18:07callenthey share knowledge through various channels, people get educated, but it's a bag of tools. Not one big "thing" you have to buy into whole-sale.
18:07sandbagsbut my point was not "Rails" as in Rails but "Rails" as in an app/framework that is widely popular and draws a lot of attention
18:07callensandbags: pre-rails Ruby and the current state of Clojure are not comparable at all.
18:07sandbagscallen: i was not comparing them so that's fine
18:07callenClojure as a community embraces libraries that stand alone. There wasn't a good library ecosystem for making web apps in Ruby back then.
18:08sandbagsyes sorry maybe i wasn't clear
18:08callenit's a mistake to believe that because things like Sinatra, which isn't Rails, exist now, that they somehow existed before Rails did. They didn't.
18:08sandbagsi wasn't implying that Clojure needs an equivalent to Rails the web framework
18:08nopromptsandbags: the down side of text. we can't here your voice or see your facial expressions.
18:08callenRuby web + the usual attendant libraries that come with writing web apps was a wasteland.
18:08callenI only used Ruby for dev-ops back then and I could tell it was bad.
18:09callenRails, for all people like to complain about it, brought a lot of lifeblood into the Ruby community.
18:09sdegutisWhere does set! live?
18:09callensdegutis: in the gateless gate, through which one must pass.
18:09sandbagscallen: which is more the point i was driving at
18:09noprompt(var set!)
18:09noprompt,(var set!)
18:09clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve var: set! in this context, compiling:(NO_SOURCE_PATH:0:0)>
18:09brehautsdegutis: its a special form
18:09brehautsdegutis: it exists in the compiler
18:09callensandbags: my point is that the conditions that precipitated and necessitated Rails do not exist in the Clojure community.
18:09sdegutisbrehaut: oh, neat.
18:09sandbagsand what the side-effects of that life-blood might be
18:10nopromptbrehaut: well that's good to know. :)
18:10sdegutisAnd (set!) works just like (binding)?
18:10callengiven that the conditions for such are nonexistent, it's not a very interesting question at all
18:10sandbagsyes okay, let's leave it there
18:10sdegutisWith the obvious difference of being side-effecty.
18:10asteveClassCastException java.lang.Class cannot be cast to clojure.lang.IFn user/eval1144 (NO_SOURCE_FILE:1)
18:10asteveso, where to begin with this one?
18:10brehautsandbags: heres some tools in clojure that draw in people in the way rails did: core.logic, core.async, clojurescript, datomic…
18:11callenbrehaut: yep. Datomic is why we're getting Clojure at my company.
18:11sandbagsbrehaut: i don't have any numbers but i'd find that surprising
18:11callensandbags: how long have you been writing Clojure?
18:11sandbagsbut i'm here and i have no skin in this game so :)
18:11brehautsandbags: theres also all the stuff in clojure core, persistent structures, STM, etc etc
18:12nopromptcallen: "lifebood"
18:12brehautsandbags: dont confuse a lack of library for _your_ niche interest for everyone elses
18:12sandbagsi suspect we're talking at cross-purposes
18:12sandbagsbrehaut: ?
18:12callensandbags: how long have you been writing Clojure?
18:12sandbagscallen: on and off i guess about 3 months
18:13callensandbags: yeah, best to let this conversation die then.
18:13callensandbags: you don't have a frame of reference for where the community's been or where it's headed.
18:13sandbagsfine by me
18:13brehautsandbags: your are arguing that something rails-esque (big, shiny, attractive) should exist to draw people to clojure. Im saying that there are a wide range of those things already, they just may not be the specific shiny thing you are drawn to
18:13nopromptsandbags: yes let us drain the so-called "lifeblood" from the matter.
18:13callenbrehaut: stop. seriously.
18:13brehautcallen: you are right. i should be working
18:14callenbrehaut: I don't care what you do alternately, I'd just prefer to avoid bikeshedding in this channel if possible.
18:16nopromptc'mon you guys. let's not fuss. we just told that other guy that we are nice people.
18:16sdegutisOne great thing about Clojure is that I understand everything that's going on.
18:16nopromptyou're making making me look liar.
18:16nopromptlol
18:16sdegutisI love that about Clojure code I read and write.
18:16callensdegutis: really?
18:16rasmustosdegutis: everything is a strong word
18:16sdegutisWhen I see a given function, I usually don't have to dive very deep to know what it's doing.
18:17riley526ah, "referential transparency"
18:17callenyou'd be surprised how often a library has dark corners that aren't referentially transparent.
18:17sdegutisI mean besides domain-specific functions. If it uses those, there's obviously no way of knowing what it's doing without digging.
18:18sdegutisBut I love that the vast majority of code uses functions straight out of clojure.core that I already know.
18:18sandbagssdegutis: do you mean that there's less that is implicit in your code?
18:19nopromptcallen: yes, i've seen these "dark corners" you speak of. even the syntax highlighting changes.
18:19rasmustosdegutis: I guess "knowing how the functions are used" is a bit different than knowing everything that's going on under the hood
18:19sdegutisAnd the transformation-functions mentality means any third-party lib's doc-strings are usually plenty sufficient to see how it fits into the code I'm reading.
18:19callennoprompt: libraries often have to commit deeper evils in order to be nice to use.
18:20nopromptcallen: yes. like loop/recur, transients, and the dreaded ^:dynamic *var*.
18:21nopromptso dark are these that poison the hearts of men.
18:21callenloop/recur isn't evil.
18:21callentransients aren't evil either, they just require a good reason to be used.
18:21riley526why is loop/recur evil?
18:21callennoprompt: you lack imagination. I could show you such wonderful horrors.
18:21callenriley526: it's not.
18:21callenI just said it isn't.
18:21technomancyriley526: it's low-level
18:21technomancyit doesn't belong in application-level logic
18:22nopromptriley526: it's not. i'm just heckling callen.
18:22riley526I can see the low-level argument
18:22callenwhat constitutes low-level/high-level necessary/unnecessary depends on what you're writing.
18:22callenIf you're aphyr or ztellman, you probably have a good reason.
18:22callenif you're not, then you don't.
18:23callenreally simple actually.
18:23riley526a noob clojurian like myself will reach for it all the time though
18:23riley526unfortunately.
18:23callenthat hasn't been my experience.
18:23ztellmanas much fun as it is to be the poster boy for questionable Clojure usage
18:23callenztellman: but you have an excuse, so it's okay.
18:23ztellmanI'd tend towards the answer of use loop/recur when it's simpler than function composition
18:23ztellmanwhich it is, sometimes
18:23technomancyloop/recur means either "I need crazy perf" or "I haven't thought through my problem in terms of sequences"
18:24technomancyor "I'm doing I/O" maybe
18:24nopromptriley526: no need to talk down about yourself. use the best tools in your toolbox. nothing wrong with doing what you know best.
18:24ztellmansometimes it's more indirect to express operations in terms of sequence operators
18:24nopromptriley526: unless of course that's, you know, meth or something.
18:24ztellmantechnomancy: do you disagree?
18:24technomancyztellman: can't say I've had that experience
18:24noprompttechnomancy: "crazy perf". i love it.
18:24riley526noprompt: lol, sure. I'm just recognizing inexperience.
18:25technomancybut I've been out of the loop for a while
18:25ztellmantechnomancy: especially when you're updating an accumulator that drives behavior
18:25technomancyztellman: usually the source of updates can be expressed as a sequence though
18:25technomancylike having a board game as reducing a board over a seq of moves
18:25technomancyeven if the moves haven't happened yet
18:26noprompti could definitely use some tips on how to eliminate loop/recur stuff with the new garden version i'm working on. :S
18:26technomancy(defn go [] (reduce play (init-board) (interleave player-1-moves player-2-moves)))
18:26technomancy(though you can't actually do that in go because of ko)
18:27ztellmanhaha, I'm dreading going back to my go implementation
18:27ztellmanthat code got messy in places
18:27ztellmanmostly for performance reasons, though
18:27noprompttechnomancy: what would you call loop/recur + transients? "perf madness"?
18:28technomancynoprompt: the silver lining of the cloud that is JVM startup time is that I almost never need to care about perf in leiningen
18:28technomancyany optimizations I make will have the looming spectre of startup time shadowing their glory
18:28dissipate__technomancy: time to go to another language?
18:29noncomnoprompt: i had these thoughts. i would call it "use java here".
18:29technomancyI can count on one finger the number of times I've turned on *warn-on-reflection*
18:29technomancydissipate__: well, yes: https://github.com/technomancy/grenchman/blob/master/grench.ml
18:30dissipate__technomancy: oh hell no. why not haskell?
18:30technomancydissipate__: https://mobile.twitter.com/technomancy/status/367661164433383424?p=v
18:31TimMcpffft
18:31dissipate__technomancy: you got me there. :P
18:32technomancyocaml lets you distribute smaller native binaries too, but unfortunately that's only true if you don't use the Jane Street libs
18:32technomancythis program is nearly all IO anyway
18:35sdegutisWhat's a good language for when you want to write something quickly that executes quickly and starts up quickly and can do high-level things like encode/decode JSON and such?
18:37technomancyOCaml is kinda crappy at JSON actually
18:37brehauttechnomancy: thats ok, most languages are
18:37hiredmanneeds type classes
18:40s4muelHi all...I'm working with a crappy nested datastructure and wondering if this is the 'idiomatic' way to arrive at the result. https://www.refheap.com/18334
18:41technomancysdegutis: some of that depends on whether you can assume an existing runtime
18:41s4muelit is the result i want, it just seems kind of messy. But then again, I'm new here.
18:43technomancysdegutis: if you can't, racket would be my suggestion; you can get a 700kb distributable that starts in 200ms without the headache of reading json from a static type system
18:45noprompts4muel: i don't see anything "wrong" with that. of course it really depends on the problem you are trying to solve.
18:46noprompts4muel: if you're using 1.5.1+ you can use mapv instead of the (vec (map combo
18:46dnolens4muel: why is the latter data desirable over the former in your case?
18:47s4muelnoprompt: thanks, that's the kind of thing i was looking for.
18:48sandbagsthanks for all the help earlier & conversation folks. g'night
18:51s4mueldnolen: Going into a different structure with different keys, etc. This seemed easier to do some destructuring in one function and then go from there with anything else I have to write. It captures all the data I'm interested in.
18:52dnolens4muel: so you want to access your data structure via numeric indexes?
18:52s4muelAlthough it might be better to create another map.
18:53dnolens4muel: yeah that's what I was wondering
18:53s4muelI just thought about that -- I was focusing more on the destructuring of the original response
18:53s4muelThanks :)
19:32powrtocI'm playing with core.async at the REPL and wondering why if I (def c (chan 1)) then run (<!! c) and press CTRL-C to interrupt the repl in emacs... next if I do (future (>!! c 10) (prn "done")) it prints done... which seems to indicate the channel hasn't synchronised and has lost my message as the next read op (<!! c) blocks immediately
19:32powrtocany ideas?
19:32powrtocdoes core.async handle interrupts/threads properly?
20:03lgs32adid anybody here get clojurec to work?
20:04lgs32ae. g. pass the tests?
20:05llambdawhat's the best way to reference a local clojure project as a dep in another project? preferably via lein :)
20:05lgs32allambda: lein install
20:05llambdacool, thanks
20:05lgs32athen simply use it in project.clj under dependencies
20:06llambdaalso i'll be distributing this to my team via a private repo on github. what's the best way for them to use it in their projects?
20:06llambdaclone and do the same or is there an easier way?
20:06lgs32ahmmmz a maven repository?
20:15coventryllambda: It's also useful to symlink the local project in checkouts/ under the dependent project. That way, lein immediately picks up changes. https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies
20:24llambdacoventry: thank you, that's very helpful!
20:28squidzsomething like [{:key "a" :val "a"} {:key "b" :val "b"} {:key "c" :val "c"}] -> [[m1 m2] [m2 m3] [m1 m3]] where the m[i] are the three input maps
20:29squidzwhat would be a good way to get all possible combinations of an array of javascript object>? each javascript object looks like {key: a val: 1} and I want all non repeating combinations of an array of those types of objects
20:30squidzsomething like [{:key "a" :val "a"} {:key "b" :val "b"} {:key "c" :val "c"}] -> [[m1 m2] [m2 m3] [m1 m3]] where the m[i] are the three input maps
20:32brehaut,(let [l [{:key "a" :val "a"} {:key "b" :val "b"} {:key "c" :val "c"}]] (for [a l b l] [a b]))
20:32clojurebot([{:key "a", :val "a"} {:key "a", :val "a"}] [{:key "a", :val "a"} {:key "b", :val "b"}] [{:key "a", :val "a"} {:key "c", :val "c"}] [{:key "b", :val "b"} {:key "a", :val "a"}] [{:key "b", :val "b"} {:key "b", :val "b"}] ...)
20:33brehaut,(let [l [{:key "a" :val "a"} {:key "b" :val "b"} {:key "c" :val "c"}]] (for [a l b l :when (not= a b)] [a b]))
20:33clojurebot([{:key "a", :val "a"} {:key "b", :val "b"}] [{:key "a", :val "a"} {:key "c", :val "c"}] [{:key "b", :val "b"} {:key "a", :val "a"}] [{:key "b", :val "b"} {:key "c", :val "c"}] [{:key "c", :val "c"} {:key "a", :val "a"}] ...)
20:34squidzbrehaut: yes that works when working with clojure datastructes but not clojurescript structures
20:34squidzi mean javascript objects
20:35brehautsquidz: you want javascript objects inside the seq?
20:36nopromptsquidz: you could always use js->clj or write a custom macro. worse you could extend ILookup, etc to object.
20:36squidzyes the input are js objects and the output pairs need to be too
20:37squidzI had exaclty the example you have, but js-objects seem to be tricker with equality
20:37nopromptsquidz: also remember you have the google closure libraries at your disposal too like goog.object etc.
20:38squidzI dont't want to convert if I can avoid it, like I said the input is already js objects and the output should be too
20:49lgs32adoes somebody know a librabry that can parse http-link escapes like %20 to what they actually mean, e.g. space
20:52lgs32anevermind, remembering .net.URI
20:55coventry,(do (defn & []) (defn silly-buggers [& args] [& args]) (silly-buggers))
20:55clojurebot#<Exception java.lang.Exception: SANBOX DENIED>
20:56callen"SANBOX"
21:00seangrov`callen: It will never be fixed.
21:01yedianyone know of a good article about how to do basic user authentucation in web apps? i've done it b4, but I want to know if there are certain best practices that i'm currently not aware of
21:01callenseangrov`: I actually submitted a PR to fix it.
21:01technomancyuse bcrypt
21:01callenseangrov`: it got merged. it was never deployed.
21:02technomancy^ the extent of my knowledge
21:02callenyedi: use bcrypt. don't store important information in cookies without encryption.
21:02callenif you want to be really elite use scrypt.
21:02yediscrypt works too right?
21:02yedioh word
21:02technomancydelegate to another site with oauth if you can get away with it
21:03callenI...wouldn't do that.
21:03callenusers tend to hate you if you force oauth on them without it being purposeful.
21:03callenthere needs to be a reason other than, "I refuse to write 4 lines of code for a login functionality"
21:05yedi4 lines of code is a little bit of an understatement,,,
21:05coventryYeah, there's the password reset functionality.
21:16tufflaxIs there a nicer way of doing (if x (conj xs x) xs)? x can never be false, just nil
21:20bbloomtufflax: that seems nice enough to me, but what about (cond-> xs x (conj x))
21:22tufflaxbbloom: yeah maybe it is nice enough :p
21:22bbloomtufflax: i frequently define utility functions like these: (def conjs (fnil conj #{})) and (def conjv (fnil conj []))
21:23bbloomif you need that a bunch in one file, just make conjx or something
21:23technomancycallen: what about "I refuse to add a database to accommodate people who hate github"?
21:25callentechnomancy: punish them by making your database an append log on disk.
21:25callena naive implementation.
21:25callentechnomancy: the more they use the service, the slower it gets (scanning the append log)
21:25callenif they complain? explain the above.
21:25callenyedi: is that a challenge?
21:26callenyedi: because if it's a challenge...
21:31tufflaxbbloom: ok but that does not really solve my current problem, unless im missing something... :p
21:31bbloomtufflax: no, i was just saying that trivial functions like that aren't so bad to just assign names to them. just defn- and you're good
21:31bbloomtufflax: don't be afraid to factor out little functions even if they are only useful once :-)
21:32tufflaxyeah i do that, usually in let/letfn though
21:32xeqicallen: I am interested to see how far you get in a user system with 4 lines
21:37callenxeqi: I could make a minimally functional login/auth, logout, session mgmt system for a web app in 4 lines.
21:37xeqicallen: password reset, password change, username change ?
21:38xeqi+ views
21:39callendon't move the goal post.
21:39callenhere's a better proposal, "you have 4 lines. How much of a user mgmt system can you implement?"
21:39xeqihmm, does oauth give those?
21:39callennot really, no.
21:39callenit's just login/auth @ Oauth2
21:39callenand I can replace that in 1 or 2 lines
21:40callenI can do logout and session management in 1 or 2 more lines.
21:40callenI think I could certainly replace OAuth2 in 4 lines of code for a single web app.
21:40calleneasy-peesy.
21:40callenand by replace, I don't mean, "emulate the API", I mean, functionally replace the purpose of it with an in-house login/auth
21:41technomancyyou get password reset with oauth
21:41technomancyyou even get 2fa now with github oauth
21:41callenthat's...what...no.
21:41callenthat
21:41callenis not oauth.
21:41callenthat's vendor specific stuff related to their own account management
21:41callenoauth2 is a framework, it's not even a protocol. It doesn't even technically know what a password is beyond a vague notion of "credentials"
21:42callenall it handles is, "I'm a third party, and I need to know that 'Jane from Github' is in fact Jane from Github. Can you @Github tell me that they are who they say they are?"
21:42callenI'm going to tweet that now so people can understand OAuth.
21:43callen-12, fuck.
21:43sdegutistechnomancy: noted, thanks
21:43xeqi.. so its an API that hooks into a system that already has password reset and change and views built
21:44callenxeqi: correctamunde.
21:44callenbut the "purpose" of it is login/auth specifically
21:44callenbecause you're authenticating the person
21:44callenbut you still have to manage the sessions and logout even if you use OAuth.
21:44xeqicertainly seems like the goal posts for an equivalent system should include those
21:44technomancycallen: if you use oauth from github, you get those benefits
21:46callenxeqi: you realize that because Clojure is a Lisp, I can ride the 4 line limitation straight to hell right?
21:46technomancycallen: no column limitation you mean? =P
21:47xeqicallen: you could do that with any language with multi statements per line
21:47technomancyruby has a 5-line wiki
21:47technomancy(one of the lines is a shebang)
21:48callenhttp://viewsourcecode.org/why/redhanded/bits/batsmansFiveLineWiki.html
21:48xeqitechnomancy: no `Redmine.new` and poof I have a wiki? awww
21:51yedicallen: well obviously
21:52brehauttechnomancy: http://www.c2.com/cgi/wiki?ShortestWikiContest
21:52brehauttechnomancy: no surprises but perl has 4 lines including shebang
21:53asdf__question for you all. Is there a quick/simple way to replace nils in a list with zeros?
21:54brehaut,(map #(if (nil? %) 0 %) [1 nil 2 nil 3])
21:54clojurebot(1 0 2 0 3)
21:54technomancybrehaut: well hello mister fancy pants
21:55brehautasdf__: but for bonus marks ##(map (fnil identity 0) [1 nil 2 nil 3])
21:55lazybot⇒ (1 0 2 0 3)
21:55asdf__thanks. I should say that I really want to map multiply two sequences where there could be nils. So not necessarily replace the nils, just ignore them or something
21:56brehaut,(remove nil? [1 nil 2 nil])
21:56clojurebot(1 2)
21:57brehautim not sure what you mean by map multiply
21:57asdf__not exactly, I'm looking for something like (reduce + (map * [1 nil 2 nil] [5 6 1 2])) that should end up as 7
21:58brehautasdf__: fnil again
21:58brehaut,(apply + (map (fnil * 0 0) [1 nil 2 nil] [5 6 1 2])))
21:58clojurebot7
21:59brehaut,(doc fnil)
21:59clojurebot"([f x] [f x y] [f x y z]); Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x. Higher arity versions can replace arguments in the second and third positions (y, z). Note that the function f can take any number of arguments, not just the one(s) being nil-patched."
22:00asdf__ahh look at that. awesome
22:01asdf__quick thing then. difference between apply and reduce
22:01brehautapply happens to be a tiny bit smarter with variadic functions
22:02brehautthe seq gets marshalled into something something varargs rather than something else wheres amalloy to explain it
22:02gfredericksclojurebot: where is amalloy to explain it
22:02clojurebotc'est bon!
22:07asdf__one more thing. you guys are always really helpful. way easier to ask questions here than google/stack overflow.
22:16gfredericks(inc #clojure)
22:16lazybot⇒ 5
22:30amalloybrehaut: wut
22:30brehautamalloy: apply vs reduce for functions like +
22:30gfredericksamalloy: thank god you're here!
22:31brehautamalloy: i know thres a reason, but ive comepletely mangled it in my remembering
22:31amalloy*shrug* i mean, reduce is marginally faster for +, because apply just delegates to reduce
22:31amalloybut for str, apply is way way faster than reduce
22:32brehautoh. well there you go. i auto cargo culted and got it wrong
22:32callenI thought apply was really slow in some cases for some reason.
22:36john2x,(doc apply)
22:37clojurebot"([f args] [f x args] [f x y args] [f x y z args] [f a b c d ...]); Applies fn f to the argument list formed by prepending intervening arguments to args."
22:37Scriptoris it largely because apply handles multiple arities?
22:37john2x,(doc reduce)
22:37clojurebot"([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i...
22:37Scriptorup to 4 or so arguments before the varargs
22:42bjaI think ring+compojure+ring-edn is making me lazy
22:45callenbja: tragedy.
23:01sdegutistechnomancy: found a real life picture of Leiningen: https://www.dropbox.com/s/4m4l77gfoykmp0m/leiningen.jpg
23:06fkey(for [x [1 2 3 4]] ((fn [y] (* y)) x)) works , but
23:06fkey (for [x [1 2 3 4]] ((fn [y] (.log js/console "test")) x)) doesn't...why is that so?
23:07coventryfor returns a lazy sequence. Realize it with doall.
23:08gfredericksor use doseq instead
23:09fkeyif i replace for with doseq, it logs to console only item, and never gain
23:09fkeyis doseq lazy too?
23:09sdegutis,(doc doseq)
23:09clojurebot"([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."
23:10xeqidoseq is not lazy
23:11coventryfkey: Does the console avoid printing repeat messages? You might try logging a message which varies with x.
23:11fkeycoventry: will try that
23:11fkeycoventry: i guess firebug was hiding some info from me, thanks
23:13xeqifkey: also, you don't need to create an (fn [y] ...) and immediatly call it in a for/doseq. (doseq [x [1 2 3 4]] (.log js/console (str "test " x))) will work
23:14fkeyxeqi: thanks, i originally tried that but was confused why the logging wasn't working heh
23:27coventryWhat's the common thread in catch, finally and "&"? They seem to all go through clojure.lang.Compiler/InvokeExpr.parse (they all have null in the "specials" map, so analyzeSeq sends forms starting with these to InvokeExpr.parse.) And the logic in InvokeExpr seems totally unrelated.
23:27coventryDon't need to understand this for my current project, but I am curious.
23:27yediforgot clabango doesn't support else
23:27yedireally need to move to selmer
23:40ddellacostaI'm curious what people took away from Alex Miller's piece: http://tech.puredanger.com/2013/08/31/clojure-and-testing/
23:40ddellacostaI've been thinking about testing in Clojure a lot lately because I have a strong feeling that "I'm not doing it right."
23:41ddellacostabut it could be because the system I'm building now is badly designed
23:41ddellacostawhich complicates my tests.