#clojure log - Sep 04 2013

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

0:04 callen: seangrove: gads that was ages ago. Irish pub on Clement by Laurel Heights.

0:30 futile: hey isnt someone in here a literature nerd?

0:31 i just read The Raven to the kids and it was fantastic and im lookin for recommendations of similar short poems to read to them

0:39 Xorlev: futile: Anything by Shel Silverstein. I'm also a fan of "Poetry 180", a compendium by Billy Collins who himself is a very accomplished poet.

0:41 brainproxy: futile: I like Hopkins

0:42 there was a little collection of some of his poems, "Immortal Diamond"

0:43 futile: btw what i loved mostly about the raven was all the alliterations and rhyming and perfect timing

0:44 brainproxy: probably Hopkins most famous short poem: http://www.potw.org/archive/potw29.html

0:45 "Spring and Fall"

0:45 for something more epic, Chesterton's "The Ballad of the White Horse" might fit the bill

0:45 https://en.wikipedia.org/wiki/The_Ballad_of_the_White_Horse

0:46 https://en.wikisource.org/wiki/The_Ballad_of_the_White_Horse

0:46 futile: chesty!

0:47 oh man i didnt know he was a poet too, thought he was just a catholic hero

0:47 brainproxy: quite the poet

0:49 his novel "A Man Who Was Thursday" is lesser read but is a real classic imo

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

0:49 brainproxy: *The Man...

0:49 futile: brainproxy: thanks for this ill have to check him out more thoroughly :)

0:50 brainproxy: np

0:50 futile: i think he was one of the people who convinced me that you dont have to sacrifice intellectual integrity to believe in catholicism

0:50 <3

0:51 technomancy: a "lesser read"???

0:51 lazybot: technomancy: Oh, absolutely.

0:51 technomancy: bollocks

0:55 futile: technomancy: you can only say that if you lived in UK for > 80% of your life

0:56 technomancy: I grew up in the commonwealth; leave me alone =P

0:56 futile: hey i dont make the rules

0:57 (inc brainproxy)

0:57 lazybot: ⇒ 2

0:59 brainproxy: what is wrong with "lesser read" (I'm a yank btw)

1:01 technomancy: I think Thursday is his best work

1:01 futile: welp, time to eat cookies and try to make progress in this immutable recursive descent Clojure parser.

1:02 technomancy: depends what he meant by "lesser read", could very well mean less popular

1:02 amalloy: futile: is there a reason you aren't just using something already built? there are some excellent parsers in clojure

1:02 brainproxy: fair 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.

1:02 amalloy: eg, instaparse arrived on the scene to great fanfare a couple months ago, and looks great

1:02 seabre: parsatron is pretty cool

1:03 brainproxy: I've met few that have read Thursday, but that may be Americans

1:03 futile: amalloy: well part of it is that its a learning experience

1:03 amalloy: 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.

1:06 amalloy_: and thirdly learning another parser lib seems like it might be just as difficult as writing a clojure parser

1:07 brehaut: futile: do you know BNF? you know instaparse

1:07 futile: i do not

1:07 not well enough to write it reliably

1:09 technomancy: brainproxy: oh, I interpreted "read" as a noun rather than a verb

1:09 which is I guess what futile said

1:09 as you were

1:09 futile: technomancy: no i also interpreted it as a noun

1:09 * technomancy calls off the guards

1:10 futile: technomancy: i still thought "a lesser read" could regard the "popularity" attribute rather than "quality"

1:10 thats how i interpreted it.

1:18 callen: brehaut: Instaparse is maaaaaaaagic

1:18 <3

1:19 futile: is instaparse self-hosting yet?

1:19 callen: futile: you'd probably learn more from learning an existing parser through-and-through than you would writing a recursive descent parser.

1:19 the 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.

1:20 those were the parsers*

1:21 futile: callen: i wrote a simple lisp parser in C once successfully

1:21 i just think it was really badly done and i want to learn how to do it smarter.

1:21 so im reading about it

1:22 brehaut: futile: https://github.com/brehaut/inc-clojure-brush/blob/master/shBrushClojure.js#L64-L385

1:23 futile: brehaut: thats similar to what i had before, but now i want to do it in idiomatic clojure

1:23 brehaut: idiomatic clojure would be dont write a recursive decent parser by hand when there are good tools already in existence ;)

1:24 futile: i came up with this trick to emulate "read" and "peek"... (partition 2 1 [:end] string)

1:34 seabre: I can't read "came up with this trick" without thinking about this and its variations: http://www.oneweirdkerneltrick.com/paperfigs/vapnik.jpg

1:34 Thanks internet.

1:37 futile: seabre: parsers *hate* me!

1:38 seabre: lol

1:38 futile: become a parent in 280 days with this one weird trick

1:39 aw its not on knowyourmeme

2:13 going unconscious for few hours

2:14 Raynes: Where will you be when the LSD hits?

2:15 http://imgur.com/r/funny/Fr3V0St

3:42 hhenkel_: Good morning everyone, what is the best way to check a string for a substring or regex?

3:44 fredyr: ,(.contains "coool" "ool")

3:44 clojurebot: true

3:45 hhenkel_: fredyr: oh, that's easy...I was thinking about much more complicated stuff...thanks!

3:45 fredyr: :)

3:47 hhenkel_: fredyr: Is that also usable with a regex?

3:47 fredyr: (.matches "ceaol" "c[aeo]{3}l")

3:47 you'll have to use matches then

3:47 ,(.matches "ceaol" "c[aeo]{3}l")

3:47 clojurebot: true

3:48 hhenkel_: fredyr: ah, okay. Thanks again!

3:48 fredyr: sure np

3:50 the java String docs is useful for these things btw

3:50 http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

3:51 hhenkel_: fredyr: another question regarding "matches", you're not using #" " syntax there for regex. is that because it is a java function.

3:53 Oh, i meant ? not . at the end of the sentence... ;)

3:53 fredyr: yes the String api takes strings for regexes and not java.util.regex.Pattern

3:56 hhenkel_: okay

3:58 fredyr: the Patterns are great when you want to take apart a string

3:58 shaungilchrist: what is state of the art for cljs pprint?

4:00 fredyr: ,(let [[a b c d] (re-matches #"(c)([aeo]{3})(l)" "coool")] [a b c d])

4:00 clojurebot: ["coool" "c" "ooo" "l"]

4:04 sheldonh: g'damn! clojure's map applies over multiple collections. hot

4:06 * Raynes hands sheldonh a towel

4:15 ambrosebs_: bbloom: check the mailing list...

4:52 sheldonh: is there a core function that does (partial apply concat)?

5:08 ddellacosta: sheldonh: just coming to Clojure?

5:08 oh, I guess you wrote that like an hour ago, d'oh

5:08 ucb: heh

5:08 ddellacosta: haha

5:09 ucb: I actually read sheldonh's comment as hash-maps being applicable to multiple collections :(

5:14 sheldonh: ddellacosta: yup :)

5:15 ddellacosta: sheldonh: all I wanted to say was, I expect you'll have a lot of those "hot!" moments from now on. ;-)

5:15 ucb: does nrepl support who-calls?

5:15 ddellacosta: ucb: I didn't think of that...

5:15 ucb: nrepl.el even

5:15 ddellacosta: ucb: sorry, what's who-calls?

5:16 ucb: ddellacosta: I have a history for misreading things

5:16 ddellacosta: ucb: haha, I do too, so don't feel bad.

5:16 ucb: ddellacosta: say you're looking at the definition of a function, you want to know where it's used, i.e. who-calls the fn?

5:16 ddellacosta: ucb: pooh, gotcha. Yeah, I dunno, sorry. But that sounds pretty freaking handy.

5:16 pooh = oooh on spellcheck

5:16 ucb: that's because it is :)

5:17 heh

5:17 ddellacosta: hahaha

5:17 ucb: my phone's spellchecker corrected hope to hippie

5:17 ddellacosta: nice

5:17 something poetic about that one

5:17 ucb: ended up telling my friend "hippie you can come"

5:17 ddellacosta: hahahaha, seriously, just laughed out loud at that

5:17 good thing I had nothing in my mouth

5:17 ucb: I laughed too

5:17 he never texted back

5:17 ddellacosta: ucb: hahahahahahaha

5:17 ucb: so there goes another relationship ruined by technology

5:18 ddellacosta: ucb: he's lost

5:18 hahaha

5:18 ucb: heh

5:18 ddellacosta: brilliant

5:20 fredyr: :)

5:20 clgv: can I query attributes of nested maps in monger?

5:25 NeedMoreDesu: I 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?

5:27 ddellacosta: NeedMoreDesu: what do you mean, problems with whitespaces?

5:28 NeedMoreDesu: %20 in their places

5:29 ddellacosta: NeedMoreDesu: still confused. %20 is where?

5:30 NeedMoreDesu: #<URL file:/D:/folder1/folder2/new%20folder/xxx-0.1.0-SNAPSHOT-standalone.jar>

5:31 It's "new folder"

5:31 ddellacosta: NeedMoreDesu: okay, so, you need that as a string with spaces replacing the %20?

5:32 NeedMoreDesu: Hmmm.. solving problem so directly? Never thoght about that lol.

5:33 ddellacosta: ,(java.net.URLDecoder/decode "new%20folder")

5:33 clojurebot: "new folder"

5:33 ddellacosta: …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.

5:34 NeedMoreDesu: are you in Japan, btw, or is your handle unrelated to Japanese?

5:35 hhenkel_: 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.

5:35 NeedMoreDesu: ddellacosta: might be related, since I have japanese locale.

5:35 hhenkel_: 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")))))

5:36 ddellacosta: NeedMoreDesu: just curious, since I'm in Japan. Always interested to hear if there are an folks in Japan using Clojure.

5:36 hhenkel_: What would be the best solution for that?

5:36 ddellacosta: hhenkel_: please use refheap, do not paste code into IRC

5:36 ordnungswidrig: hhenkel_: (if (.matches x #"...") blabla x)

5:37 ddellacosta: hhenkel_: also, don't know why you need an atom for that, just use loop and recur

5:37 NeedMoreDesu: ddellacosta: Sorry, I'm not from japan, just used it to avoid crash problems in some jp games >_>

5:37 ordnungswidrig: hhenkel_: together with map: (map #(if (= "foo" %) "bar" %) ["some" "foo" "bar" "baz"])

5:37 ddellacosta: NeedMoreDesu: ah, okay...haha

5:37 hhenkel_: ordnungswidrig: ? I learned earlier on that this is a java function and therefore string regex are used. This part works.

5:38 Anderkent: NeedMoreDesu: 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

5:38 ordnungswidrig: hhenkel_: you want to update some values in a list, right?

5:38 hhenkel_: ddellacosta: Thouht if I want to make a persistent change to a list I need a atom or ref, don't i?

5:39 ordnungswidrig: yes.

5:39 ddellacosta: hhenkel_: sure, but if you are doing it inside a doseq it defeats the purpose

5:39 ordnungswidrig: hhenkel_: the most easy is to use map, like above, you can then use update-in to update a list which is a map vaue.

5:39 Anderkent: NeedMoreDesu: if you want to get a filesystem path from that, do (.getAbsolutePath (File. my-url)) for example

5:39 NeedMoreDesu: Anderkent: I used it as input to clojure.java.io/file. ddellacosta's solution works.

5:40 Anderkent: you can just pass it to file without modifying it

5:40 sheldonh: ddellacosta: fortunately, i dipped into haskell last year, so it's not completely overwhelming. someone here recommended 4clojure.com, which i've been enjoying enormously

5:40 clojurebot: It's greek to me.

5:40 ordnungswidrig: hhenkel_: i'll put together an example, wait a minute

5:40 ddellacosta: sheldonh: I love 4clojure, I gotta get back to it myself. Welcome! I need to get into Haskell myself, now that you mention it...

5:40 hhenkel_: ordnungswidrig: okay, thanks. my ? was regarding the (.matches ...) as that part works for me.

5:41 sheldonh: ddellacosta: 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 :)

5:41 clgv: hhenkel_: there is `re-matches` to get rid of the unnecessary interop

5:42 ddellacosta: sheldonh: ah, good to know. Yeah, I've heard it's kind of a major mind bender. Looking forward to learning more.

5:42 NeedMoreDesu: hhenkel_: you change values of a vector with assoc, just like maps.

5:42 assoc, get, update-in works

5:42 hhenkel_: clgv: okay, fredyr pointed me to .matches earlier on.

5:43 clgv: hhenkel_: for basic takss look for a clojure function first ;)

5:43 *tasks

5:43 ordnungswidrig: https://www.refheap.com/18292

5:43 hhenkel_: clgv: I had much more complicated stuff in mind, so that was allready a good thing... ;)

5:44 ordnungswidrig: hhenkel_: saw that link?

5:44 clgv: hhenkel_: 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

5:45 the `(.matches ...)`

5:45 sheldonh: ddellacosta: advice from my limited haskell experience: stop at least 2 hours before bed time :)

5:45 amalloy: there's really no reason to use .matches and an ugly double-escaped string instead of re-matches and a regex literal

5:45 hhenkel_: ordnungswidrig: Yes, thanks. I think it takes me some time till I totaly understand what going on. Thank you!

5:45 ordnungswidrig: hhenkel_: more ideomatic would be https://www.refheap.com/18293

5:46 hhenkel_: decompose your problem!

5:47 hhenkel_: 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

5:48 hhenkel_: ordnungswidrig: Divide and conquer...I'll try but currently I'm fighting with the missing knowledge vocabular.

5:48 clgv: hhenkel_: do you want to build a templating system? if so, you should know there are already several libs for that

5:48 ordnungswidrig: hhenkel_: we're here to help

5:49 hhenkel_: you need to understand, that you cannot update a list or vector. You will always be returned a new instance.

5:50 hhenkel_: to be honest, there are ways for in-place modification but these should be reserved for performance sensitive application

5:50 ddellacosta: sheldonh: point taken!

5:50 hhenkel_: 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".

5:50 clgv: ordnungswidrig: well phrased like that you cannot update any immutable data structure ;)

5:51 ordnungswidrig: clgv: huh, I first read "immortal".

5:51 clgv: haha

5:52 hhenkel_: ordnungswidrig: I'll try to find my way around the immutible data structures but I'm spoiled by oop... ;)

5:52 clgv: ordnungswidrig: I think you meant that you cannot update lists efficiently meaning in constant time.

5:52 clojurebot: Titim gan éirí ort.

5:52 hhenkel_: I'm off for lunch. Read you later.

5:52 clgv: *elements in lists I wanted to say

5:52 ordnungswidrig: clgv: you cannot?

5:53 clgv: except from the first element ok ;)

5:53 Apage43: I get to spend this week implementing mutable data structures that will be hit from multiple threads, in C++. I am not excited.

5:53 hyPiRion: Apage43: oh dear

5:54 * ddellacosta pats Apage43 on the back

5:54 clgv: Apage43: is there nothing in boost for that?

5:54 hyPiRion: Apage43: For hash maps, do the HAMT/Concurrent tries from Bagwell, http://skillsmatter.com/podcast/scala/parallel-algorithms-data-structures

5:55 Apage43: The guy here needs to be an ordered map of some sort

5:57 hyPiRion: oh dear =/

5:57 It's possible with the HAMTs, but it's a bit of thinking I *think*.

5:58 Apage43: If 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.

6:00 hyPiRion: Oh, then the concurrent tries are a great fit. But the GCing is a bit iffy, yes.

6:00 Apage43: A single week only? =/

6:01 Apage43: possibly more =P

6:01 (realistically more)

6:01 but the made up number is a week

6:25 ddellacosta: what does the double-dot function do in clojurescript?

6:25 (.. something fn1 fn2) ?

6:26 it seems a bit like doto or -> but not sure exactly what is going on

6:26 can't find it in docs

6:26 hyPiRion: ddellacosta: macroexpand it

6:27 ,(macroexpand-1 '(.. something f1 f2))

6:27 clojurebot: (.. (. something f1) f2)

6:27 hyPiRion: ,(clojure.walk/macroexpand-all '(.. something f1 f2))

6:27 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>

6:27 ddellacosta: hyPiRion: um, can I do that with CLJS?

6:27 hyPiRion: ddellacosta: I will guess the macro also exists in cljs

6:28 it's just a chaining of .call functions

6:28 ddellacosta: …is it in Clojure too? only ever seen it in CLJS

6:28 oh well, look at that

6:28 nevermind.

6:29 hyPiRion: I guess I don't see why you'd use this over ->

6:29 clgv: yes it is. pretty useful :D

6:29 ddellacosta: hyPiRion: I guess it's more concise if you are doing java interop

6:29 hyPiRion: yeah

6:29 ddellacosta: well then, I learned me somethin' new. Thanks hyPiRion.

6:30 hyPiRion: np

6:31 ,(.. "string" (substring 2) (equals "ring"))

6:31 clojurebot: true

6:42 hhenkel_: 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...

6:43 ordnungswidrig: hhenkel_: what does manipulate mean? do you need to change once (after reading) or again and again?

6:43 hhenkel: ordnungswidrig: once after I read the config from file I want to make some kind of "variable substitution".

6:44 ordnungswidrig: hhenkel: then you build a function that returns the data substituted

6:45 clgv: is there already a lib implementing a query language similar to the stuff for DOMs for nested clojure data structures?

6:46 ordnungswidrig: clgv: get-in?

6:47 clgv: ordnungswidrig: no that is only map/vector access.

6:48 hhenkel: ordnungswidrig: 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?

6:48 ordnungswidrig: I would simple bind the final result like that (def config (substitute-all-the-vars (read-config-from-file "config.edn")))

6:49 hhenkel: ordnungswidrig: hmm, okay that sounds reasonable...I find it really hard to switch my thinking on how to implement stuff.

6:50 ordnungswidrig: hhenkel: once you switched it will be even harder to look back. :)

6:52 hhenkel: ordnungswidrig: It allready starts, currently I have to teach python to one of my coworkers.... :(

7:01 ordnungswidrig: 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?

7:03 ordnungswidrig: hhenkel: you need up changes multiple keys?

7:04 clgv: hhenkel: if it is a map-tree you can use clojure.walk but be careful with metadata

7:04 ordnungswidrig: there is also fmap in the ns algo.generic

7:04 hhenkel: ordnungswidrig: yes, as it is a "user" provided config there maybe the chance that more "variables" need to be altered.

7:06 ordnungswidrig: ,(clojure.algo.generic.functor/fmap inc {:a 1 :b 2})

7:06 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.algo.generic.functor>

7:11 hhenkel: clgv: 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"

7:14 clgv: hhenkel: dont know how your "tree"s are defined

7:18 hhenkel: clgv: more or less like this: { :hosts { :host1 { :protocol "http" :port 9101 :actions [ "action1" "${actions.action2}" ]}}}

7:18 clgv: hhenkel: and you want to replace only leaf-nodes?

7:19 hhenkel: My current assumption is that only values could contain "variables" to make life easier.

7:19 But in theory it could also be possible to have keys that need to be replaced.

7:22 clgv: hhenkel: well clojure (pre/post)walk will walk all clojure collecions so these are inner nodes and all non-collections (say "atoms") are leafs

7:23 hhenkel: prewalk calls the given function before walking the children, postwalk does so after.

7:26 Anderkent: clgv: you mean clojure.walk/walk? I don't think that goes into maps

7:26 clgv: Anderkent: it does

7:26 Anderkent: ,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})

7:26 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>

7:26 Anderkent: blah

7:26 clgv: &(use 'clojure.walk)

7:26 lazybot: ⇒ nil

7:26 Anderkent: ,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})

7:26 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.walk>

7:26 Anderkent: ,(use 'clojure.walk)

7:26 clojurebot: nil

7:26 Anderkent: ,(clojure.walk/walk #(do (println %) (if (= % "$foo") "bar" %)) #(do %) {:a {:b "$foo"} :c {:d :f}})

7:26 clojurebot: [:a {:b $foo}]\n[:c {:d :f}]\n{:a {:b "$foo"}, :c {:d :f}}

7:27 Anderkent: walk is for sexps afaik

7:27 clgv: &(postwalk (fn [x] (if (integer? x) (inc x) x)) {:a {:b 1}})

7:27 lazybot: ⇒ {:a {:b 2}}

7:27 clgv: Anderkent: there you go ^^

7:28 Anderkent: ah, I see. So the inner given to walk should recurse, I suppose

7:28 ,(clojure.walk/postwalk-replace {"$foo" "bar" :c :notc} {:a {:b "$foo"} :c {:d :f}})

7:28 clojurebot: {:a {:b "bar"}, :notc {:d :f}}

7:29 Anderkent: cool

7:29 hhenkel: clgv: so, prewalk executes before it traverses and postwalk first traverses and then executes?

7:30 clgv: hhenkel: sounds about right, yes

7:31 Anderkent: also look at how ugly walk is because of this stupid idea that emptying a MapEntry gives nil.

7:31 clgv: &(pewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (integer? (val x)) x) x)) {:a {:b 1 :c "bla"}})

7:31 lazybot: java.lang.RuntimeException: Unable to resolve symbol: pewalk in this context

7:31 clgv: &(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (integer? (val x)) x) x)) {:a {:b 1 :c "bla"}})

7:31 lazybot: ⇒ {}

7:32 clgv: &(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (or (map? x) (integer? (val x))) x) x)) {:a {:b 1 :c "bla"}})

7:32 lazybot: ⇒ {}

7:32 clgv: ok nvm

7:33 &(prewalk (fn [x] (if (instance? clojure.lang.MapEntry x) (when (or (map? (val x)) (integer? (val x))) x) x)) {:a {:b 1 :c "bla"}})

7:33 lazybot: ⇒ {:a {:b 1}}

7:45 sheldonh: when 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?

7:46 Anderkent: sheldonh: yes, sandboxed environments dont let you def stuff

7:46 ,(def bad-boy 1)

7:46 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

7:46 sheldonh: thanks :)

7:49 clgv: Anderkent: not necessarily, you can setup your sandboy with clojail allowing `def` and just cleaning up all namespaces every 10mins or so

7:50 *sandbox

7:50 Anderkent: would be really useful. but both clojurebots mistrust us too much to do that ;)

7:51 sheldonh: you server, your rules ;)

7:55 clgv: sheldonh: btw. 4clojure literally copies your code at the position of the __

8:01 sheldonh: clgv: three cheers for referential transparency :)

8:02 destructuring lazy, infinite sequences. hohoho!

8:12 it'll be very interesting coming back to my first round of 4clojure solutions, armed with the learning from same

8:17 clgv: no clojure 1.5 on 4clojure :(

8:22 borkdude: Is it possible to enforce a constraint on a string field in Datomic, to be always lowercase?

8:24 clgv: borkdude: are there any constraints for attribute values possible?

8:24 borkdude: clgv don't know, this is what I'm asking I guess :)

8:25 clgv: borkdude: well, if it were than the had to be part of the schema right?

8:25 augustl: borkdude: no, you need to wrap datomic to handle that

8:25 the datomic peer lib compares more to the raw mysql lib than an actual "useful" data storage lib :)

8:26 I hope they add validation tx functions at some point though, not just fact creation tx functions

8:27 clgv: augustl: since you seem to have some datomic value let me ask the following question: when exactly do transactions in datomic fail?

8:27 augustl: you 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.

8:28 but if you refer to a symbol/attribute that doesn't exist you'll get an error, and so on

8:28 ro_st: is there a variant of group-by that removes the key from the seq?

8:29 clgv: augustl: ok I meant failure for trying to commit confliciting changes to the same entity for example

8:30 augustl: clgv: there's not a lot of conflict that can happen :)

8:30 in 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)

8:31 clgv: augustl: 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

8:31 *two peers

8:32 augustl: clgv: the transactor gets to decide which one wins, since writes are single threaded

8:32 clgv: or 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?

8:33 augustl: what you describe is optimistic locking - you'd nede to implement that yourself (I've done it for one of my systems once)

8:34 clgv: hmm well I think I need a better description how the transactions work in datomic. one video and the webpage were not sufficient it seems

8:34 augustl: a tx consists of the facts only, datomic doesn't care about the state of the peer that created it

8:34 clgv: in short, it's a single queue of transactions that gets processed one at a time

8:35 this is the only way to guarantee 100% consistency

8:35 clgv: yeah so much I know.

8:35 ro_st: you 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

8:36 augustl: clgv: my Datomic knowledge is accreted through #datomic, various videos, blog posts, and having talked to Rich Hickey at a conference once :)

8:36 clgv: so the commiters need to make sure that they do not post conflicting facts?

8:36 augustl: clgv: "conflicting facts" - what do you mean by that?

8:36 clgv: augustl: in a logic sense of the problem domain of the facts.

8:36 ro_st: clgv: you can always go back in time to see what the facts were in the past

8:37 augustl: the only conflict I'm aware of is that you transacton contains a fact that matches the existing fact

8:37 anything else is just written

8:37 clgv: ro_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

8:37 augustl: so the conflict is in your interpretation of the data, not in datomic itself?

8:38 clgv: yes

8:38 ro_st: clgv: unless you had transactor functions that checked your problem model prior to commit

8:38 augustl: also keep in mind that a transaction is fully atomic. You won't see some values from one transaction and other values from another

8:38 ro_st: you can give your transactor process extra jars in its class path if you need to call out to domain logic

8:38 clgv: e.g. you calculate the average of a set of numbers and then someone change this set of numbers right before your commit

8:38 augustl: (assuming you have two transactions for the same attributes and the same entities, but setting different values)

8:38 clgv: that you would have to do in a transactoin function to be able to have it consistent

8:39 ro_st: if you really, really wanted to, you could validate your whole problem model / database inside every transaction

8:39 clgv: augustl: so for large calculation you would have a compare and swap function as transactor function or similar?

8:39 ro_st: nothing stopping you from doing that. it'll make transactions much slower to process, of course, but you would always have a consistent model

8:40 if 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

8:40 augustl: clgv: 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]]

8:41 in 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

8:41 see: stored procedures ;)

8:42 clgv: augustl: ah ok interesting. thank you :D

8:42 augustl: ..which is why datomic is probably not a good fit if you need a lot of writes and this computation takes a long time

8:42 clgv: augustl: that means stored procedures are used more often than in sql databases?

8:43 augustl: clgv: yeah. You can't do chatty client-side transactions with datomic

8:43 ro_st: you'd only want to use transactor functions when you need consistency. otherwise, do your work in the peers

8:44 augustl: only transaction functions with isolation level 9000 :)

8:45 an 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

8:45 or perhaps use a cache instead of storing it normalized in the db

8:46 clgv: augustl: datomic stores `many`-relation attributes as sets right? so I can not have duplicate values in there?

8:47 ro_st: you can have multiple entities with the same value on a given attribute, and then relate those entities as a set

8:48 eg a group entity with 3 user entities all with the :name "Mike"

8:48 clgv: ok let me rephrase: I need to get multiple values that are equal for that attribute for the following calculations

8:48 is :db.cardinality/many only possible for :db.type/ref?

8:49 augustl: clgv: you can have cardinality/many for any attribute

8:49 ro_st: it's totally possible for any of the types you can use

8:49 clgv: I want an attribute with :db.type/double and :db.cardinality/many

8:49 augustl: I'm not actually sure about how equality is determined. I would guess the same as Clojure sets

8:49 clgv: augustl: that would be a problem

8:51 augustl: clgv: you could always use entities, of course, and store the doubles as attributes on that entity

8:52 clgv: with size explosion :/

8:53 ro_st: entities are basically just longs, clgv

8:54 clgv: ro_st: that means I double the size per double value...

8:55 ro_st: way more than double the size

8:55 datomic stores each datom at least 3 times. and each datom is four scalar values

8:56 augustl: clgv: keep in mind that entities are not stored in Datomic. Entities are just derived from the facts in the index

8:57 which is why you get an emity entity instead of nil when you do (datomic.api/entity db some-eid-that-does-not-exist)

8:57 so 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

8:59 clgv: equality semantics are the same as in clojure. so no choice but to store them as byte array :(

9:01 augustl: ..or to use an extra entity :)

9:02 clgv: no. that is more complicated than just one call to convert to byte-array and one call to convert back to double-array

9:03 I dont want to query for the single values anyway.

9:03 augustl: clgv: sure thing, just wanted to be pedantic ref "no choice but to" :)

9:03 clgv: I'd wish all 4 clojure data structures could be plain values

9:05 augustl: would 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

9:06 clgv: augustl: yeah that should be fixed as well. ;)

10:24 augustl: 2 seconds per transactions for importing data into datomic seems slow to me. what am I doing wrong

10:24 ?

10:26 augustl: clgv: depends on your transaction and your data

10:26 what kind of workload are we talking about?

10:27 clgv: augustl: the transaction is a tree of entities summing up to 1,3MB when serialized to bytes

10:27 augustl: sounds about right to me, maybe, perhaps :)

10:27 I've got little experience with large transactions

10:28 clgv: should I try to put more then one of those entity trees in the transaction?

10:28 augustl: do you have any large attributes? Or is it you I discussed this with in #datomic yesterday? :)

10:28 s/attributes/single values/

10:28 clgv: I'd have to import for 2 days with that speed

10:29 augustl: yes that was me. I got rid of the large binary attributes. now all binary attributes are below 20K

10:30 augustl: I use the recommended setting ratios for 4g RAM for 8g

10:32 augustl: sounds 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:43 hhenkel: I'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:47 Anderkent: hhenkel: you must return the unaltered node if your condition doesn't match

10:47 clgv: hhenkel: your else-case has to return something

10:47 Anderkent: right now you're saying 'if it's a string replace test with TEST, otherwise return nil'

10:48 also, never ever make one-armed ifs. If you want nil for the else-clause, use when.

10:51 clgv: hhenkel: https://www.refheap.com/18308

10:58 ddellacosta: what's the inverse of filter?

10:59 clgv: ddellacosta: remove

10:59 ddellacosta: clgv: d'oh, obvious. Many thanks!

10:59 clgv: &(remove odd? (range 10))

10:59 lazybot: ⇒ (0 2 4 6 8)

10:59 ddellacosta: lazybot just made a cool guy smiley at me.

10:59 curse you lazybot!

11:00 Anderkent: (0

11:00 clgv: 8)

11:07 hhenkel: clgv: Your code gives me errors, it seems like there is one bracket in the wrong position.

11:07 But I think I got it fixed...now I have to check what you changed...

11:08 Anderkent: okay...I'll try to remember that.

11:08 clgv: I added one `%` and removed the unnecessary `do` - it was supposed to end up in the else branch of your `if`

11:11 hhenkel: clgv: Thanks, it is now working, very good hint that the else is causing the nil, wasn't aware of that.

11:14 noncom: is this an intended behavior of (ns)? : https://www.refheap.com/18311

11:15 when i got hey/pool and it fully behaves like a namespace inside a namespace, I was surprised

11:15 gfredericks: noncom: 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:16 which would probably cause you some trouble but is apparently not checked for

11:16 sandbags: anyone recommend a CSV parsing library? I can see 3 on clojars.org but no details (e.g. api docs) about any of them

11:16 gfredericks: sandbags: data.csv works fine for me

11:17 sandbags: amusingly that is not one of the ones listed by clojars :)

11:17 noncom: gfredericks: why does it create hey/pool and not pool as i have specified?

11:18 gfredericks: noncom: because of how ` works

11:18 sandbags: ah, i see data.csv is at maven

11:18 gfredericks: ,`pool

11:18 clojurebot: sandbox/pool

11:18 Anderkent: noncom: because ` namespaces all symbols

11:18 gfredericks: noncom: ^

11:18 sandbags: thanks gfredericks

11:18 gfredericks: sandbags: np

11:18 noncom: ok, how do i make it in the macro not to be prepended there?

11:18 Anderkent: use ' not `

11:18 gfredericks: sandbags: yeah the core libs don't get deployed to clojars

11:18 Anderkent: or do `~'symbol

11:18 sandbags: is data.csv a core lib?

11:18 Anderkent: ,`~'pool

11:18 clojurebot: pool

11:18 gfredericks: sandbags: yeah

11:19 sandbags: i'd have expected it to be core.data.csv or somehting

11:19 maybe i am missing something about the convention

11:19 gfredericks: Anderkent: `~' is an interesting emoticon

11:19 sandbags: was there some way i could have known it was a core lib?

11:19 noncom: what is the diff between ' and ~' in this case?

11:19 gfredericks: sandbags: the naming convention includes data.*, java.*, and maybe some others

11:19 Anderkent: the difference is that with ~' everything else will be properly namespaced, whereas with ' nothing will be namespaced

11:19 clojurebot: Ok.

11:19 sandbags: ah, so it's kind of an informal thing

11:19 "learn the prefixes for core"

11:19 gfredericks: :)

11:19 sandbags: ok

11:20 Anderkent: ,`(+ 1 ~'nothing)

11:20 clojurebot: (clojure.core/+ 1 nothing)

11:20 sandbags: also am i missing where this stuff is documented?

11:20 Anderkent: ,'(+ 1 nothing)

11:20 clojurebot: (+ 1 nothing)

11:20 gfredericks: sandbags: the clojure github page would give you a sense for what exists

11:20 sandbags: or is the documentation "read the source" ?

11:20 gfredericks: sandbags: I don't know of a good resource for contrib libs except for that diaspora page

11:21 sandbags: okay i'm just used to (spoiled maybe) by ruby gems where, typically, the rdoc is published

11:21 gfredericks: $google where did contrib go

11:21 lazybot: [Where Did Clojure.Contrib Go - Clojure Development] http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

11:21 sandbags: so at least you tend to have easy access to the api docs

11:21 noncom: hehe, well, thanks! i'll go do more things with that.. :)

11:22 gfredericks: sandbags: the rdocs are all published in the same place?

11:22 Anderkent: wait what? data.csv is not a core lib. it lives in a separate jar

11:22 gfredericks: Anderkent: "contrib lib" is probably what I should have said

11:22 I did not mean that it's distributed with the clojure jar

11:22 sandbags: okay so it's easy enough to rustle up the docs

11:22 noncom: ,'(+ 1 'nothing)

11:22 clojurebot: (+ 1 (quote nothing))

11:22 Anderkent: yeah that's kinda different.

11:23 sandbags: i do wish more of them came with examples, but i guess you can always find something to complain about :)

11:23 noncom: ,'(+ 1 ~'nothing)

11:23 clojurebot: (+ 1 (clojure.core/unquote (quote nothing)))

11:23 Anderkent: sandbags: 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:23 gfredericks: noncom: shameless plug: http://www.infoq.com/presentations/macros-clojure-west-2013

11:24 Anderkent: I guess you can just take a look at https://github.com/clojure to see all org.clojure/* projects

11:24 sandbags: Anderkent: 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:24 and having the right instinct about where to look

11:24 Anderkent: my workflow when I find a lib is usually

11:24 sandbags: although i would have thought that some kind of consolidated search over clojars and maven would be useful

11:25 hanDerPeder: does anyone know if clj-webdriver is actively maintained?

11:25 Anderkent: lein try org.clojure/data.csv , (require '[clojure.data.csv :as c]) (c/<tab completion>)

11:25 and see what comes up :P

11:25 gfredericks: sandbags: well I don't think "maven" is a thing you can search over. But it could be better than it is, yeah

11:25 sandbags: :)

11:25 gfredericks: i meant search.maven.org

11:25 Anderkent: you can search maven, but that's not usually what you want to do

11:26 and you can't trust mvn central anyway

11:26 sandbags: good to know :)

11:26 xeqi: I believe sonatype is calling that "central"

11:26 Anderkent: central's broken by design, and you should really strive to use sonatype/clojars instead of central whenever you can

11:26 sandbags: btw Anderkent, why do you quote your vector in that require?

11:27 Anderkent: sandbags: because it's not in the ns macro

11:27 xeqi: Anderkent: can you expand on the "broken by design" ?

11:27 Anderkent: xeqi: there's no access control. Once you have push to mvn central, you can push to any group/artifact, and even overwrite versions

11:27 sandbags: Anderkent: (answer-expand-1 "because it's not in the ns macro")

11:28 xeqi: Anderkent: ah, right

11:28 Anderkent: sandbags: the ns macro quotes symbols for you, so (ns (:require [foo.bar :as zip])) works.

11:28 but if you try ##(require non.quoted.symbol)

11:28 lazybot: java.lang.ClassNotFoundException: non.quoted.symbol

11:28 Anderkent: it will not work.

11:28 futile: well of *course* writing my parser was so hard, i forgot to split it into a tokenize phase and parse phase

11:28 Anderkent: ##(require clojure.java.io)

11:28 lazybot: java.lang.ClassNotFoundException: clojure.java.io

11:28 sandbags: ah, you're using (require ...) not (ns ... (require ...)) i see

11:28 * futile sighs

11:28 Anderkent: ##(require 'clojure.java.io)

11:28 lazybot: ⇒ nil

11:28 Anderkent: yep

11:28 futile: thats super functional, too. how could i be so silly.

11:28 sandbags: I am finding require to be the bane of my existence at the moment

11:29 noncom: gfredericks: thanks for the reference! seems like that presentation will be very informative for me

11:29 sandbags: i have to use it often but I cannot, yet, internalise the rules for writing it properly

11:29 Anderkent: sandbags: you should use :require within ns form. And you rarely should have a non-ns require in your code

11:29 sandbags: i did smile when i watched Chas Emerick's talk about clojure issues

11:29 Anderkent: it only really comes up in the repl

11:30 sandbags: Anderkent: i meant "ns require" rather than the require function

11:30 noncom: sandbag: what were the issues?

11:30 sandbags: maybe just my brain getting old

11:30 noncom: i just find it hard to remember the rules for writing a require correclty

11:30 and, almost every time, have to refer back to a previous time ive done it or one of my books

11:30 Anderkent: right. you'll learn it eventually, but in general you only need (ns (:require [full.lib.name :as alias] ...))

11:31 noncom: sandbags: there are "two different" require, :require in the ns form and (require)

11:31 Anderkent: all the other stuff like :refer is optional :)

11:31 hhenkel: Anyone around who can explain why the string "${part2.test2.1}" get replaced with "TESTTEST" using (clojure.string/replace % #".*" "TEST") ?

11:31 sandbags: i'm better than i was, but it's just the thing i hit *every* time i am writing code

11:31 noncom: although they are the same ultimately

11:31 hhenkel: Hmm, seems like .+ is better....?

11:31 sandbags: what's the difference between (ns (:require ...)) and (ns (require ...)) btw?

11:31 i find i am using them interchangably

11:32 noncom: futile: what is that parser you're talking about?

11:32 futile: a parser

11:32 noncom: im pissing everyone off by writing my own Clojure parser in Clojure

11:32 Anderkent: hhenkel: it does seem like a bug.

11:32 futile: im also using my own testing lib to do it

11:32 ToxicFrog: hhenkel: .* is zero or more of any character. .+ is one or more. The .* might be matching the empty string at the start or end.

11:32 noncom: sandbags: (:require) is simply a parameter to ns macro, it is not a function call

11:32 (require) is a function call

11:33 ToxicFrog: I've run into similar issues with java's regex library returning spurious empty string matches.

11:33 clgv: sandbags: you should be using (:require ...) within `ns`

11:33 sandbags: clgv: ok, i've no idea quite where I got the (ns (require ...)) pattern from, presumably misreading something

11:33 thanks guys

11:33 noncom: noncom: as (ns) is a macro, the list (:require [stuff :as s]) does not get parsed until it is pulled apart inside (ns)

11:33 Anderkent: sandbags: it should be (:require) not require :)

11:34 noncom: (ns (require)) is definitely not what you want, yeah

11:34 sandbags: Understood :)

11:34 unfortunately it seems to work (for some value of work involving not raising any errors and doing some kind of require)

11:35 noncom: futile: cool! i think that everybody should welcome Clojure parser in Clojure?

11:35 sandbags: so it wasn't obvious IWDIW

11:35 Anderkent: hhenkel: ##(.replaceAll "a" ".*" "FOO")

11:35 lazybot: ⇒ "FOOFOO"

11:35 Anderkent: so I guess it's a java thing

11:35 futile: noncom: they say i should use instaparse or something that already exists

11:35 Anderkent: basically the .* matches twice - first for the entire string, then the empty string

11:35 futile: noncom: which generally is good advice, but not when the goal is to learn how to write a parser

11:35 xeqi: futile: you should write your own monadic parser combinator library

11:35 futile: ahhhh!!!!

11:36 * futile shrieks in terror

11:36 sandbags: xeqi: hand him a big smelly yakk and a razor why don't you!

11:36 arcatan: you should write your own applicative parser combinator library

11:36 xeqi: fine fine, you can stick with an applicative functors .... blah

11:37 hhenkel: Anderkent: yeah, seems like you're right.

11:37 sandbags: hrmm.. 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:37 futile: xeqi: Be that word our sign of parting, nerd or fiend!

11:37 noncom: i 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:37 sandbags: so that I can locate a file in the project root folder

11:37 futile: xeqi: Leave no parenthesis as a token of that lie thy soul hath spoken!

11:38 noncom: sandbags: try (System/getProperty "user.dir")

11:38 * futile may have read The Raven too many times last night

11:38 technomancy: http://timberglund.com/blog/2012/08/03/the-maven/

11:38 sandbags: noncom: nice, thanks

11:38 technomancy: futile: ^

11:38 futile: technomancy: oh it has a video too??

11:38 lazybot: futile: What are you, crazy? Of course not!

11:39 technomancy: it is. a masterpiece.

11:40 futile: heh wow

11:40 "Leave my project's build unbroken!—quit my central source code store!"

11:41 shoulda said "quit my DVCS store"

11:43 sandbags: hrmm... 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:44 (and literal "/"'s i mean)

11:44 Anderkent: sandbags: java.nio.file.Path?

11:45 futile: so 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:45 Anderkent: yeah, it's not like anyone reads it

11:45 ;P

11:45 noncom: futile: try and see! it's free :D

11:46 sandbags: i use (str) to concat strings

11:46 futile: i guess im concerned because ive announced 2 other testing libs already, to a loud negative critical reaction

11:46 sandbags: noncom: ta

11:47 Anderkent: well, 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:47 noncom: futile: well, maybe it is worth to have someone test your libs prior to announcement then

11:48 i too had that sloppy feeling posting an announcement recently

11:48 futile: Anderkent: 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:48 muhoo: i am deeply suspicious of any "unifying" effort

11:48 futile: the 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:48 muhoo: without even reading the details of what it's trying to unify.

11:49 sandbags: futile: perhaps, as an alternative strategy, see if someone else can prove your testing library on their project and do a co-announcement?

11:49 futile: sandbags: thats a good idea

11:50 dnolen: squidz: I fixed the set bug from yesterday

11:50 noncom: sandbags: 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:50 futile: Even 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:50 sandbags: noncom: yep

11:51 noncom: futile: i think that whatever comes up, it is for your benifit

11:51 futile: Ooooh, 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:52 noncom: you mean it is different from the peers?

11:53 futile: For 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:53 noncom: no, I mean the reasons I like it are because it does things differently than peers

11:54 And that makes me a huge asshat.

11:54 * futile sighs

11:55 * sandbags sighs

11:55 noncom: futile: well, when i come into such a position, i write a short document which outlines and describes all the benifits

11:55 sandbags: so it seems like i am still struggling with damn requires

11:56 noncom: then read it several times

11:56 and think if i can present the outline points as a win

11:56 then, if i can manage tht, usually people react good

11:56 sandbags: whatsup?

11:56 futile: I think "referential transparency" might be the shortest way of describing why I wanted it in the first place.

11:57 arohner: futile: link to the lib(s)?

11:57 sandbags: something 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:57 futile: arohner: https://github.com/sdegutis/nevermore

11:57 But I gotta rename it.

12:00 noncom: sandbags: 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:00 sandbags: i am sure this probably all becomes subconscious at some point

12:00 but as a beginner it has the feeling of being a huge piece of grit in my eye

12:00 often making me feel functionally illiterate

12:01 noncom: i mean how i put "org.clojure/data.csv" in project.clj but I require clojure.data.csv

12:01 and 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:01 noncom: heh

12:02 sandbags: and 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:02 noncom: well, 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:02 sandbags: noncom: this is my point

12:03 noncom: yeah all that was happening to me too

12:03 sandbags: right 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:04 like i say, i presume at some point i'll just internalise all the mucking about and will no longer notice it any more

12:04 but it seems like a less than ideal setup right now

12:04 noncom: if i use (defmacro m [x] '(+ 1 ~x)) how do i make it to resolve x as the param?

12:04 sandbags: of 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:05 noncom: sandbags: right. i noticed that phenomenon to be widely spread over ppl

12:05 clgv: noncom: unquote unly works with backtick (defmacro m [x] `(+ 1 ~x))

12:05 *only

12:05 noncom: clgv: so no way?

12:05 futile: sandbags: I haven't run into that issue.

12:06 sandbags: as 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:06 clgv: noncom: see the example above. that work

12:06 sandbags: did you try eclipse+counterclockwise?

12:06 sandbags: clgv: no

12:06 noncom: clgv: but i cant use backtick because it will incorrectly resolve (ns boo) to (ns current-ns/boo) :(

12:06 clgv: sandbags: you should

12:06 futile: sandbags: 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:06 noncom: sandbags: i use ccw, give it a try

12:07 clgv: noncom: what exatly do you want to do

12:07 sandbags: futile: i am hoping for paredit in a future version of LT, it looks amazing

12:07 futile: sandbags: 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:07 sandbags: clgv: i may have been too scarred by use of Eclipse in a past life

12:07 clgv: ccw has most of paredit as well ;)

12:08 sandbags: i no longer remember anything about it, i just feel a deep pain somewhere around my kidneys when I read its name

12:09 Anderkent: eclipse 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:09 sandbags: I often use Vim but never managed to get a working Vim+Clojure setup

12:09 noncom: clgv: https://www.refheap.com/18316

12:10 sandbags: i've given up trying to learn emacs... 3 attempts is enough (even if my RSI makes it not a great choice)

12:10 Anderkent: noncom: that's the correct resolution

12:10 sandbags: other than bits of paraedit what would CCW give me that you can't live without?

12:10 what's the main selling point?

12:10 noncom: Anderkent: yes, sorry, it is corerect, but not what i need

12:10 Anderkent: if you want to strip out the namespace then you need to do `(+ 1 ~@'x)

12:11 eh wait that's not right

12:11 clgv: sandbags: what do you use right now?

12:11 sandbags: i'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:11 noncom: sandbags: ccw is heaven

12:12 sandbags: well i guess i should probably give it a try

12:12 does it have a debugger?

12:12 noncom: what is debugger?

12:12 sandbags: LT is making some steps through it's watches

12:12 but i would, occasionally, like to be able to single-step

12:12 although i have no idea how that would work with clojure code

12:12 where so much can be happening in "a line"

12:12 noncom: i do not know, i never use that kind of debug

12:12 clgv: noncom: does `x` contain 'boo at compile time?

12:13 sandbags: ah the joys of starbucks wi-fi and 200mb downloads

12:13 noncom: clgv: well, i am not sure...

12:14 Anderkent: noncom: what exactly are you trying to do

12:14 clgv: noncom: 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:15 noncom: given an example macro call and the desired expansion of the macro call

12:16 squidz: dnolen: awesome. When do you think I will be able to use it?

12:16 noncom: well, you see, that macros, `z` in the refheap post is called from a string that is passed through (eval (read-string s)) first

12:16 Anderkent: on runtime or compile time?

12:16 noncom: that (eval (readstring s)) happens inside the namespace where z is defined

12:17 Anderkent: runtime... :( ?

12:17 Anderkent: right, so you're calling z like (z evalled-string), not (z {:literal :map})

12:17 noncom: yes

12:17 Anderkent: and you want to extract a symbol from evalled string on runtime and call ns on it

12:17 why is it a macro?

12:18 why not just (defn z [dict] (ns (:param dict))) ?

12:18 noncom: hmmm...

12:18 clgv: noncom: the use of `eval` there probably adds to your confusion ;)

12:18 noncom: clgv: sure :)

12:19 well, really.. why is this macro...

12:19 clgv: noncom: cant you make a minimal viable gist that should run if the macro was implemented correctly?

12:19 noncom: must defn be better

12:20 sandbags: okay Java interop isn't so hideous after all

12:20 noncom: clgv: 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:20 Anderkent: noncom: as I said. Just make it a function. Trying to force it to be a macro for no reason is just additional pain

12:21 sandbags: yeah it's pretty convenient. I find myself firing up clojure repl just to explore java libs etc.

12:21 easier than trying to write java :P

12:21 sandbags: well i've not written any Java since about 2005 so i'd have to agree with you there

12:21 although i am somewhat surprised more of the IO stuff isn't wrapped

12:22 i mean, it's not so hideous to write (.exists (io/file "path")) but...

12:22 noncom: that puzzled me too

12:22 why so?

12:23 Anderkent: yeah, lack of nice wrappers for io/nio is slightly painful

12:23 but i guess it's mostly because it's tedius work to create them

12:23 sandbags: i guess, to be fair

12:23 Anderkent: clojure.java.io is already pretty nice :)

12:23 sandbags: i'm really complaining about writing ".exists" rather than "exists?"

12:24 gfredericks: sandbags: (-> "path" io/file .exists)

12:24 Anderkent: something like file/exists? rather than exists?, probably :P

12:24 futile: ok, renamed my testing lib

12:24 clgv: noncom: 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:24 futile: no more trying to steal technomancy's naming approach

12:24 sandbags: gfredericks: yes that's quite nice ... still haven't quite internalized the -> and ->> macros yet

12:24 clgv: noncom: given that information it is much much easier to help

12:24 gfredericks: sandbags: once you do they become indispensible

12:24 shaungilchrist: sandbags: this was just posted on the mailing list http://www.youtube.com/watch?v=qxE5wDbt964

12:25 sandbags: thanks

12:25 noncom: clgv: 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:25 Anderkent: it'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:26 noncom: it's less about the context and more about the purpose

12:26 there'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:27 sandbags: this 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:27 clgv: noncom: you provide a macro implementation try and nothing more..

12:27 Anderkent: sandbags: yes. Eclipse is horrible in that way.

12:27 dnolen: squidz: probably next week some time, there a few more patches I would like to get in.

12:27 sandbags: clojurians do seem to be on a sigil bender lately

12:27 Anderkent: sandbags: 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:27 sandbags: at least that's my perception as someone reasonably new to the platform

12:28 squidz: dnolen: cool thanks for the quick work

12:28 noncom: oh 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:29 sandbags: macro's are enticing because they're one of the reasons you're there in the first place

12:29 noncom: no-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:29 sandbags: but as with many people i've taught Ruby... you have to check your desire for massively inappropriate metaprogramming

12:30 Anderkent: macros bring complexity, if you can do something with a function you shuold always choose that

12:30 dnolen: sandbags: 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:30 Anderkent: only when there's significant benefit shuold you consider writing a macro

12:30 clgv: sandbags: in clojure dev I hardly use any eclipse menu ;)

12:31 * futile considers alternate nicks

12:31 sandbags: dnolen: yeah on reflection i am bound to agree with you

12:31 it was kind of a knee-jerk reaction

12:31 oh god i am not sure i can use Eclipse

12:32 this is bringing back horrible nightmarish familiarity

12:32 noncom: me too, i just have the editor, the project tree and the repl

12:32 sandbags: of software designed by people who should clearly should have nothing to do with the design of software

12:32 indeed who should be actively disbarred from the profession

12:32 Anderkent: sandbags: c'mon, i bet it didnt even hang on you yet

12:33 rasmusto: Anderkent: it's not the software hanging that he's worried about

12:33 sandbags: it's trying its best

12:33 noncom: dnolen: can a robot do that? (wrapping i mean)

12:34 Anderkent: you could generate the bindings that mirror classes one to one, but what's the point

12:34 it'd only make sense to wrap stuff if you improve the api

12:34 sandbags: "Problem occurred. Creation problems. Invalid project description."

12:34 there is no field for project description

12:34 dnolen: noncom: think about the differences between hosts, it really is pointless - file handling in Java is sync, file handling in Node is not.

12:35 * sandbags the prosecution rests

12:35 dnolen: noncom: these sorts of things better handled in well thought out libraries

12:35 noncom: with specific goals

12:35 Anderkent: sandbags: what kind of project are you importing? mvn or lein?

12:35 sandbags: i am trying to create one

12:35 noncom: yeah, right..

12:35 Anderkent: don't do that. Create the project on filesystem, then import into eclipse

12:35 sandbags: of course! i should have realised :)

12:35 Anderkent: i mean I guess ccw probably gives you some kind of creator

12:35 but why learn all that

12:36 noncom: Anderkent: I can say that creating clojure projects with ccw works for me now..

12:36 there was a trouble with the creator in past versions

12:36 sandbags: oh wait... this "workspace" business.. does this need to be a folder that Eclipse can own?

12:36 noncom: yes

12:36 Anderkent: sandbags: yes. But your projects can live outside the workspace

12:36 * sandbags sighs

12:36 noncom: :)

12:37 Anderkent: I just put them in ~/.eclipse/workspaces/XXX

12:37 sandbags: i am not sure i can use software that i am going to actively hate this much, even if it does have paredit

12:37 Anderkent: treat a workspace as a config set

12:37 gfredericks: bbloom: I am curious about your "only extend protocol if you own the protocol or the type" guideline

12:37 in particular this one case I am handling

12:37 and what you think is wrong with it

12:38 sandbags: "No projects are found to import"

12:38 Anderkent: sandbags: did you pick the right type? (clojure/leiningen project I assume)

12:38 sandbags: is there some CCW specific import?

12:39 Anderkent: yes, it will be under clojure

12:39 sandbags: i don't seem to have Clojure under the import tree

12:39 Anderkent: do you have ccw installed? :P

12:39 sandbags: apparently

12:39 Anderkent: lemme fire up eclipse

12:39 (back in 10 mins)

12:40 noncom: sandbags: 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:40 or turn into lein prject.. i dont remember

12:40 Anderkent: yuck no don't do that

12:40 eclipse will do stupid stuff to your filesystem

12:40 like create ~/bin or w/e

12:40 sandbags: i definitely have CCW as I have File>New>Clojure Project

12:40 clojurebot: excusez-moi

12:40 noncom: but it was the official instruction

12:40 sandbags: well perhaps i shouldn't sound so definitive

12:41 who knows? maybe i have half of CCW

12:41 and it's severed head is wandering around someone in the upper regions of memory

12:42 Anderkent: hm, you're right that it doesn't have import

12:42 that's weird

12:43 noncom: Anderkent: 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:43 i believe it treats (:params dict) as a list

12:43 coz it quotes it..

12:43 ?

12:43 Anderkent: ah yes

12:43 sandbags: well this is great, i have now created a new Clojure project

12:43 and... where the hell is it?

12:43 futile: ha

12:43 noncom: sandbags: is it in the file explorer?

12:43 sandbags: oh i see, i need the workbench

12:43 noncom: of the eclipse i mean

12:44 sandbags: how is this thing not better? this seems like exactly the experience i had last time i tried Eclipse

12:44 how can almost 10 years not improve a thing AT ALL?

12:44 that or it wither and die

12:44 technomancy: ten years ago it didn't support clojure =)

12:44 sandbags: it supposes that people are using this piece of shit and living with it

12:45 noncom: sandbags: i believe that most of your current feelings are induced by the destructive imprint from the past


12:45 i 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:45 Anderkent: it's not slow, your machine is slow! At least you have the minimum 16GB ram right?

12:45 sandbags: ah well, there we go

12:45 Anderkent: ah, 8gb ram is your problem

12:45 noncom: ahah

12:45 Anderkent: you're in java land

12:45 sandbags: i'll try it on the Mac Pro later

12:46 technomancy: ed doesn't waste space on my timex sinclair you guys.

12:46 opqdonut: just use emacs and nrepl

12:46 sandbags: noncom: you could well be right

12:46 opqdonut: non e possiblé

12:46 but i have to say i am feeling a lot better about LightTable's shortcomings right about now :)

12:46 technomancy: sandbags: you've done the obvious stuff like a split keyboard and moving ctrl to the right of the A key, right?

12:46 Anderkent: noncom: now htat I think about it, it might well be impossible to do what you want without something like eval

12:47 technomancy: (re: rsi)

12:47 sandbags: technomancy: yeah i have caps lock mapped to ^ as a regular habit

12:47 technomancy: i just can't get along with emacs

12:47 noncom: Anderkent: err... what would be the way with eval?

12:47 technomancy: just making sure

12:47 sandbags: i've tried several times

12:47 technomancy: thx :)

12:48 Anderkent: noncom: (defn redefine-ns [dict] (eval `(ns ~(:param dict))))

12:48 noncom: ohoh

12:48 opqdonut: instead of eval you can always just do what ns expands to

12:49 * technomancy drums his fingers and waits for his ergodox to ship

12:49 Anderkent: technomancy: to the *right* of a key?

12:49 i guess you don't like your s's

12:49 sandbags: just use vim!

12:49 :P

12:49 sandbags: Anderkent: i do!

12:49 well, for the most part

12:49 technomancy: Anderkent: derp

12:49 pbostrom: noncom: (defn z [dict] (let [sym (:param dict)] (ns sym)))

12:49 rasmusto: sandbags: have you tried vim-fireplace?

12:50 sandbags: rasmusto: i have not

12:50 Anderkent: pbostrom: that won't work, (ns sym) will declare namespace claled sym

12:50 fireplace is ok

12:50 you still need to ctrl-z to a real repl from time to time

12:50 rasmusto: sandbags: it's worth a shot, I can't speak to it vs eclipse though

12:50 Anderkent: but that's cool

12:50 sandbags: also vim-paredit

12:50 sandbags: i am already two steps from deleting eclipse again

12:50 Anderkent: must have

12:50 opqdonut: noncom: I'm not sure what you're trying to do, but this might help: https://gist.github.com/opqdonut/6439400

12:50 pbostrom: doh

12:50 rasmusto: Anderkent: real repls are overrated

12:51 sandbags: i can't imagine what it can do that would be worth living in such an application

12:51 Anderkent: sandbags: me I was looking to switching to evilmacs

12:51 rasmusto: sandbags: vim-sexp is a paredit-lite, if you like doing more vimmish editing

12:51 sandbags: and i think i've caught it before i fall into Stockholm syndrome

12:51 Anderkent: but reconfiguring all the bindings for nrepl-el etc to work with my ingrained vim motions is a real pain

12:51 noncom: thanks to you who have proposed solutions, i am currently inspecting them..

12:51 Anderkent: and evil doesn't work with paredit

12:52 which is a huge pain

12:52 rasmusto: Anderkent: the automatic insertion stuff works fine, not so much the movement commands. But there's definitely a lot of overlap

12:52 Anderkent: (dd etc. unbalance parens)

12:53 i wish i knew how to get YouCompleteMe to work with fireplace/paredit though :(

12:53 then I'd be happy in vimland

12:53 futile: Does Clojure have something like C's enum?

12:53 noncom: futile: in which sense?

12:54 rasmusto: Anderkent: <c-x><c-o> isn't good enough?

12:54 futile: Giving names to auto-incrementing numbers.

12:54 Anderkent: rasmusto: no, I like to have fuzzy completition all the time, without having to prompt for them

12:54 futile: I could enumerate through an indexed list of names and do (def) but that feels a bit odd.

12:54 rasmusto: Anderkent: ah, ok. Have you used autocomplpop?

12:55 (I love typing that btw)

12:55 Anderkent: no. I tried YouCompleteMe, which looks similar except it's not written in viml and 3 years old

12:55 but it doesn't quite work

12:55 noncom: futile: 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:56 futile: noncom: so "no"?

12:56 ok

12:56 thanks

12:56 * futile rolls it

12:56 Anderkent: futile: the fact that enums have numbers in java is an implementation detail and you shouldn't really have to use that

12:56 rasmusto: Anderkent: fireplace handles setting up omnicomplete to work with nrepl, and autocomplpop just makes autocomplete trigger while you're typing

12:56 futile: Okay better question:

12:56 Anderkent: rasmusto: right, YouCompleteMe does something similar except it also uses its own identifier-based completion system

12:57 futile: Is there a way in Clojure to create a bunch of unique-per-process constants?

12:57 Anderkent: which is cool in theory but doesnt seem to work with clojures omnifunc

12:57 futile: I suppose I could just do (def foobar) and take #'foobar, right?

12:57 Anderkent: futile: process or thread?

12:57 rasmusto: Anderkent: k, that was my impression. You should try out fireplace + <c-x><c-o> (w/ autocomplpop maybe). It works well from my experience

12:57 gfredericks: (defmacro C-enum [syms] (cons 'do (map-indexed (fn [i sym] `(def ~sym ~i)) syms)))

12:57 futile: Anderkent: I only mean I don't need it to be persisted between different times of running my app.

12:58 technomancy: futile: gensym

12:58 futile: Anderkent: It should be the same on all threads.

12:58 Anderkent: yeah gensym sounds right

12:58 gfredericks: futile: ^ how's about that macro?

12:58 futile: technomancy: But then it becomes a string. Isn't that inefficient to compare two strings?

12:58 gfredericks: hmm

12:58 Anderkent: gensym gives a symbol, symbols are interned

12:58 technomancy: ,(gensym)

12:58 clojurebot: G__31

12:58 Anderkent: symbol comparison is reference equality

12:58 futile: Oh nice! gensym it is then.

12:59 Anderkent: just dont use prefixes

12:59 futile: This should work excellently for representing different token types.

12:59 TimMc: futile: Why not keywords?

12:59 futile: TimMc: I want compile-time errors.

13:00 TimMc: That's what I was afraid of.

13:00 "Giving names to auto-incrementing numbers." is not "I want compile-time errors."

13:00 futile: Wait, I vaguely remember some email thread a month ago about how keywords are interned but symbols aren't, on account of metadata...

13:01 TimMc: sorry, I'll work on asking better questions

13:01 TimMc: Symbols are not interned, but they use interned strings.

13:01 futile: ah

13:01 rickmode: leiningen question: Is there a way to disable the AOT that's needed for a main when launching a REPL?

13:01 futile: So the interned strings are ref-compared then?

13:01 works for me

13:01 Anderkent: futile: well, they're .equal compared but .equal checks for reference equality first

13:01 I'd assume

13:03 ,(let [target (gensym "foo1")] (loop [attempt (gensym "foo")] (if (= target attempt) :broke-it (recur (gensym "foo")))))

13:03 clojurebot: :broke-it

13:04 Anderkent: just saying D

13:04 pbostrom: noncom: one more attempt (defmacro z [dict] (let [s (:param dict)] `(ns ~s)))

13:04 clgv: rickmode: yes search for lein-otf

13:04 Anderkent: pbostrom: that only works if dict is a literal map

13:05 rickmode: The 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:06 clgv: ok, I'll check that out

13:06 clgv: rickmode: the author of it is online right now (TimMc) ;)

13:07 noncom: yeah, trying, still exploring..

13:09 mimicking macroexpandlooks the closest now..., but `(ns ~s) may also work..

13:09 clojurebot: I don't understand.

13:10 clgv: noncom: you can try those in repl as well ##(let [s 'bla] `(ns ~s))

13:10 lazybot: ⇒ (clojure.core/ns bla)

13:14 solussd: why cant I put metadata on a list?

13:15 clgv: solussd: you can ##(let [l (with-meta '(1 2 3) {:awesome true})] (meta l))

13:15 lazybot: ⇒ {:awesome true}

13:15 rhg^2: 0.it's a jav interface

13:15 i forget which

13:16 solussd: but I couldnt ##(let [l ^{:type :thing} (list 1 2 3)] (meta l))

13:16 lazybot: ⇒ nil

13:16 rhg^2: java objects don't usually have it tho

13:16 noncom: i have succeeded with the way of expanding ns to its macroexpand. now i will also try the `(ns ~s) way..

13:16 clgv: solussd: there is a difference between compile time meta data and runtime metadata

13:16 solussd: ack- right.. i'm being stupid

13:16 Anderkent: solussd: ^{} puts metadata on the (list 1 2 3) list for the compiler to see

13:16 clgv: solussd: ^{...} is compile time meta data

13:17 solussd: thanks!

13:35 sandbags: any 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:37 the 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:37 mdrogalis: sandbags: It's a little long and does a few different things, but mostly looks good to me :)

13:37 sandbags: and then (assoc-in'ing) with that vector conj'd later and i wondered if it was possible to combine the two

13:37 justin_smith: sandbags: a loop where you keep grabbing the rest can be trivially made into a more idiomatic reduce

13:38 sandbags: mdrogalis: thanks... how would you see it being split up?

13:38 justin_smith: the first rows / rest rows becomes implicit with a reduce, you just get the next row on each call to the reducing function

13:38 sandbags: justin_smith: hrmm.. yes.. i'll think about that thanks

13:38 kaw: Hey, 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:38 mdrogalis: sandbags: Not sure, just have time for a quick glance.

13:38 justin_smith: also, when you are using reduce, you can talk out the doall (since reduce is not lazy)

13:39 sandbags: mdrogalis: i guess what i am asking is whether you'd extract the inner part that processes the rows into a function

13:39 at which point i guess you're pretty close to the reduce

13:39 kaw: Followed by around 100 lines of stack trace mostly from within clojure.lang, I don't know if any part of that is interesting?

13:39 sandbags: since it pulls the op out of the plumbing

13:39 justin_smith: ah, that's definitely a benefit

13:40 justin_smith: I 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:40 sandbags: justin_smith: yep i think that's what i will try, thanks again

13:41 mdrogalis: sandbags: Yes.

13:42 kaw: I 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:42 sandbags: mdrogalis: ta

13:45 kaw: Oh, it looks like that was disallowed in 1.3, so I guess clojurecheck hasn't been updated to work with 1.3

13:45 Is there any quickcheck-like for Clojure that's up-to-date?

13:47 s4muel: kaw: https://github.com/reiddraper/simple-check

13:50 kaw: s4muel: Aha, I'll check that out, thanks

13:53 callen: are there any semi-authoritative benchmarks on core.async that I should be aware of?

13:53 All I can find is the thread-ring'ish benchmark dnolen did.

13:59 danlentz: is there a "top" type in clojure? i.e. similar to T in CL? (for method dispatch using #'type)

14:00 augustl: callen: it's in snapshot so I wouldn't be surprised if there isn't a lot of that around yet

14:00 callen: augustl: should I not use it in production? :P

14:00 augustl: callen: not sure tbh. If it works it works, I guess. What could possibly go wrong, etc :)

14:01 llasram: danlentz: 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:01 danlentz: wouldd that be java.lang.Object?

14:02 dnolen: callen: what type of benchmark specifically are you looking for? at this point I find it highly unlikely to be a bottleneck

14:02 danlentz: cool tis kindly. :default should do nicely.

14:03 callen: dnolen: 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:03 dnolen: 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:04 technomancy: python doesn't have a j.u.c queue equivalent?

14:04 callen: technomancy: there's a Queue, but it doesn't really behave the way you think.

14:07 dnolen: callen: 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:11 callen: dnolen: do I have any reason to be concerned vis a vis using core.async in production?

14:11 noncom: so 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:12 callen: obviously it's a permanent rolling snapshot.

14:12 dnolen: API and functional stability being the main thing in mind.

14:21 coventry: Would it make sense for the (fn) macro to throw an error if the condition-map has keys other than :pre or :post?

14:22 muhoo: aren't :pre and :post just metadata?

14:22 and {:pre [()]} is just sugar, IIRC?

14:22 callen: that was my understanding as well.

14:23 coventry: muhoo, 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:25 callen: so it's actually yanking them out and mapping assertions across them. nifty.

14:25 coventry: (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:26 In other words, if you had some other map in there by accident, fn would silently eat it.

14:27 callen: nom nom.

14:31 dnolen: callen: high level api seems relatively stable, the only thing I know of coming down the pipe is read/write only ports

14:31 sdegutis: With 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:42 callen: sdegutis: doesn't work that way.

14:42 sdegutis: you can't put 9 mothers together and get a baby in 1 month.

14:42 sdegutis: but I'm sure the channel collectively appreciates the compliment :)

14:43 dnolen: okay, I'll just take it for granted that given the people involved, it'll be fine. Thanks.

14:44 sdegutis: callen: I've only heard of that book, not read it. But that's the example I hear every time it's referenced.

14:46 callen: sdegutis: it's the most clear way to express the thought.

14:46 sdegutis: callen: I just see so much collective potential in here, it's exciting to think of how it could all be used.

14:46 callen: it merits a read.

14:46 sdegutis: callen: have you read the book?

14:47 callen: yes, it's one of the better ones I've read on the abstract nature of software projects.

14:47 sdegutis: Cool, I might have to check it out.

14:49 Brand0: apparently I'm a moron

14:49 sdegutis: Nope.

14:49 I don't think anyone in #clojure is capable of being such.

14:50 The language has a certain barrier to entry that prevents it.

14:51 Brand0: lol

14:51 shaungilchrist: sdegutis: 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:52 sandbags: justin_smith: so i followed your advice --> https://gist.github.com/mmower/d170188fcf88d8208ee8

14:52 shaungilchrist: like 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:52 they just deliver a working function that meets the spec

14:53 I 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:53 sandbags: the one thing that bothers me now is having to use get-in as well as assoc-in

14:53 i feel like i want an assoc-in that also takes a default value

14:54 no

14:54 that makes no sense

14:54 sdegutis: shaungilchrist: as long as the bigger picture is well-defined in advance, I think that would be a really fun and feasible project.

14:55 shaungilchrist: I mean the architecture and all the details of each function's inter-operation, like you said.

14:55 rasmusto: sandbags: how about update-in?

14:55 sandbags: a ha!

14:55 rasmusto: that is i think exactly what i was after, thanks

14:56 rasmusto: any time

14:56 shaungilchrist: It 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:56 sdegutis: Is it possible to model an entire tree in an immutable fashion, whose deep nodes need to change (mutate) in response to events?

14:57 callen: sdegutis: zippers.

14:57 sdegutis: The 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:57 callen: sdegutis: zippers.

14:57 sdegutis: callen: Thanks I'll google it.

14:57 http://clojuredocs.org/clojure_core/clojure.zip/zipper

14:58 This comes with Clojure?

14:58 callen: sdegutis: yes.

14:58 sdegutis: Sounds like I'm not the first person to have this problem.

14:58 callen: zippers are important, people really need to become comfortable with them.

14:58 sdegutis: (Nor second.)

14:58 callen: sdegutis: 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:59 ToxicFrog: Why is using a zipper for this a better choice than associ-in?

14:59 sdegutis: callen: 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:59 ,(doc zip)

14:59 clojurebot: Huh?

14:59 technomancy: ~zip

14:59 clojurebot: zip 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:59 sdegutis: technomancy: yeah that

14:59 sandbags: rasmusto: yep, update-in worked a charm thanks again ... now i just have to try and remember about it :)

14:59 sdegutis: ToxicFrog: because I generate the deep-location dynamically

15:00 ToxicFrog: or rather, I find the deep-location dynamically and don't have it up-front.

15:00 ToxicFrog: Aah.

15:00 rasmusto: sandbags: I usually have at least 3 clojure cheatsheet tabs open at any given point

15:00 sdegutis: callen: Can you write a blog intro on zippers? I don't know where to start in the 'zip' namesapce.

15:00 sandbags: rasmusto: :)

15:00 ToxicFrog: Because generating it dynamically is fine as long as you have the whole path ready when you call assoc-in.

15:00 ,(inc sdegutis)

15:00 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: sdegutis in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:00 ToxicFrog: (inc sdegutis)

15:00 lazybot: ⇒ 1

15:01 sdegutis: Why?

15:01 clojurebot: sdegutis: because you can't handle the truth!

15:01 sdegutis: Oh.

15:01 callen: sdegutis: zippers are kind of annoying to learn, and doubly so to teach.

15:02 sdegutis: you might be able to bribe me into writing a blog post on them if you work on something I care about.

15:02 sdegutis: callen: 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:03 callen: 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:04 callen: sdegutis: 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:04 labor-for-labor trade.

15:04 sandbags: but how long would he have to work on it for? :)

15:05 callen: sandbags: that's a matter of negotiation and figuring out which item on my to-do list he wanted to do.

15:05 sdegutis: callen: Are you content with your Clojure editor?

15:06 callen: sdegutis: I'm an old-timer Emacs user, what do you think?

15:06 sdegutis: callen: Then you won't care about my project. So there's nothing left to do but part ways.

15:08 etehtsea: https://gist.github.com/etehtsea/ec7fca0f9539a0e398f7 why concat causes stackoverflow?

15:09 callen: sdegutis: well you're not going to get my labor for free. :P

15:09 sdegutis: callen: 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:11 Actually I might not even need zippers.

15:11 callen: I've seen a lot of people write code that got them halfway to zippers, wasting a lot of time in the process.

15:12 sdegutis: Considering 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:12 But the tree-builder will get called about 10 times per second, so it needs to be efficient and fast. Hmm.

15:14 noncom: is there a way to save the state of the whole clojure environment?

15:14 and then restore it...?

15:15 callen: noncom: you want smalltalk/CL style images? god help you.

15:15 sdegutis: noncom: Why do you want that?

15:16 noncom: yeah, i guess that kind of thing. i would explore the possibility to clone the environment on multiple computers

15:16 so it would be the same one.

15:16 nDuff: etehtsea: the literal (not Clojure-y, not efficient, but smallest-change) answer is to use (vec (last parts)) instead of just (last parts)

15:16 noncom: i can imagine doing run-time sync, but what about if i am to rise a new node

15:20 nDuff: etehtsea: ...you could use (doall last-parts) in the same way.

15:20 etehtsea: nDuff or smth like this (mapcat vec [(first parts) [e] (last parts)])

15:20 nDuff, thanks

15:21 augustl: noncom: 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:21 that won't store the env to disk of course

15:21 noncom: ideally i would like to transfer it over network :)

15:22 augustl: should be possible to model your system so all state is stored as clojure values, which is easy to serialize

15:22 noncom: right, and the program part can be transfered as sources

15:22 augustl: then again, stuff like databases is typically the solution to these kinds of problems :)

15:23 noncom: yeah

15:26 nDuff: etehtsea: ...but yeah -- it's not the initial concat that's overflowing the stack, but the attempt to realize the concat-based lazy sequence.

15:38 augustl: is 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:39 I've never written any code like that so for all I know there's no generic way to do it anyway :)

15:41 bbloom: augustl: such a merge is gonna be pretty data-specific

15:42 augustl: bbloom: that makes sense

15:43 gtrak: augustl sounds a lot like cache coherence, maybe that's a useful way to think about it?

15:44 augustl: gtrak: I'll look that up, thanks :)

15:44 hyPiRion: augustl: 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:44 augustl: I like immutability :)

15:44 hyPiRion: Granted, this only makes sense if you are writing a lot more than you are reading

15:45 augustl: I see

15:45 afaik datomic has no mutable components for achieving its periodic merges. Not that Datomic is a prime example of write scale anyway.

15:48 coventry: I'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:49 dnolen: coventry: note you can't submit pull requests

15:50 coventry: Oh. :-)

15:52 Is it worth sending the patch to clojure-dev?

15:53 Oh, here we go. http://clojure.org/patches

15:53 mdrogalis: Can ask the Clojure-dev mailing list if in doubt.

15:54 hyPiRion: you need to sign the CA to post there though, unless that has changed recently

15:54 dnolen: coventry: you need to send in a CA, open a ticket in a JIRA and attach a patch.

15:55 coventry: Thanks, everyone. Will do.

15:55 hyPiRion: You can, however, open a ticket in JIRA without a CA

15:56 squidz: what is the clojurescript type ChunkedCons? it isn't supposed to support next?

15:57 I mean is it supposed to support he protocol INext ? I'm not sure what the type is supposed to be

15:58 noncom: is there a way to know all namespaces that are currently loaded into a clojure system?

15:59 dnolen: squidz: it doesn't support INext which probably an oversight

15:59 squidz: okay so it is supposed to support it?

16:01 mdrogalis: noncom: ,(doc all-ns)

16:01 I dont know how to use clojurebot :(

16:01 noncom: ,(doc all-ns)

16:01 clojurebot: "([]); Returns a sequence of all namespaces."

16:01 dnolen: squidz: probably, http://dev.clojure.org/jira/browse/CLJS-585

16:01 hyPiRion: mdrogalis: ##()

16:01 lazybot: ⇒ ()

16:01 mdrogalis: Ah D:

16:01 dnolen: squidz: what were you doing where you wanted this?

16:01 squidz: also how are you calling next?

16:01 noncom: ## is the syntax for inline to-be-evals?

16:01 dnolen: squidz: next directly or through the protocol?

16:02 noncom: ,(all-ns)

16:02 clojurebot: (#<Namespace clojure.uuid> #<Namespace user> #<Namespace clojure.core> #<Namespace sandbox> #<Namespace clojure.repl> ...)

16:02 dnolen: squidz: next directly or through the -next protocol fn, rather

16:02 noncom: cool!

16:03 squidz: dnolen: here is the error I am getting https://www.refheap.com/18332 that is outputted from google chrome

16:03 dobry-den: Can 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:04 dnolen: squidz: yes, but what is the code that causes the error?

16:05 dobry-den: Or I guess does anyone know of a Homebrew package that wraps a .jar that I can look at

16:06 squidz: dnolen: I still have to try and find a minimal example that reproduces it

16:06 that is not dependent on other libraries etc.

16:07 xeqi: dobry-den: you could create an executable that does the call for you, like a shell script and .exe equivalent

16:09 dobry-den: xeqi: of course. thanks.

16:09 `blog` would just be a function that sends commands to an underlying .jar

16:18 squidz: dnolen: i'm not sure why the ChunkedCons is being created. It is from core.async channel that contains holds json data

16:20 dnolen: squidz: what else is in the stack trace? something must be calling -next

16:21 squidz: dnolen: forgot to paste the stack trace here it is https://www.refheap.com/18332

16:22 dnolen: squidz: what 10953, what's the code there?

16:24 cored: hello

16:24 squidz: dnolen: https://www.refheap.com/18332

16:28 dnolen: squidz: what is the name of the fn that code is in :)

16:28 squidz: dnolen: core.hash_set

16:37 dnolen: 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:40 vmarcinko: hello, 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:40 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:41 in other words, body of such command functions should be:

16:42 some-pure-fn1

16:42 some-pure-fn2

16:42 some-pure-fn3

16:42 and then...

16:42 dnolen: squidz: your bug should go away in next release, hash-set has change

16:42 vmarcinko: side-effect-fn

16:42 dnolen: squidz: still ChunkedCons should probably implement INext to avoid this altogether

16:43 squidz: dnolen: okay is there anything I can do to get my code working until the next release?

16:44 dnolen: squidz: what are you passing to set? a large vector?

16:45 squidz: yes exactly

16:46 dnolen: but I it needs to be a set because I use interesection with the results

16:47 dnolen: squidz: are you using 1859?

16:48 squidz: 1859?

16:48 dnolen: squidz: what version of ClojureScript

16:49 squidz: oh i'm not sure, is there a quick way to find out?

16:50 dnolen: squidz: you should specify it explicitly

16:50 squidz: in :dependencies in project.clj, [org.clojure/clojurescript "0.0-1859"] is what you should be using

16:51 squidz: it would help if you can confirm this issue exists in that version

16:51 squidz: okay

16:51 dnolen: squidz: make sure to remove an intermediate compiled artifacts, rm -rf target or whatever

16:52 squidz: I assume a lein clean lein cljsbuild clean will remove everything

16:52 patchwork: vmarcinko: 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:53 squidz: i'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:54 vmarcinko: patchwork: 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:54 some-pure-fn1

16:54 side-effect-fn1

16:54 some-pure-fn2

16:55 final-side-effect-fn?

16:55 dnolen: squidz: probably whatever cljsbuild pulls in, fortunately that behavior is not long for this world

16:55 patchwork: vmarcinko: Sure, as long as you encapsulate as much as you can in the pure functions

16:55 squidz: dnolen: 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:56 patchwork: vmarcinko: 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:56 vmarcinko: patchwork: 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:57 patchwork: vmarcinko: Yes, it is

16:57 dnolen: squidz: what you specify takes precedence.

16:57 patchwork: delay your side effects as long as possible

16:57 vmarcinko: ok, thanx

16:58 squidz: dnolen: 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:59 vmarcinko: patchwork: 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:59 dnolen: squidz: ok I can repro

16:59 squidz: I'll try to push another release soon

16:59 squidz: a minimal case is this, (set (map inc (into [] (range 100))))

16:59 squidz: to avoid you need to convert your result into a vector before you call set

17:00 squidz: ah okay, is it the size of the vector that makes a difference

17:01 sdegutis: Is there a side-effecty variation of (binding) that's thread-local?

17:02 dnolen: squidz: no, it's the ChunkedSeq/Cons results from calling a seq operation on a vector

17:02 ChunkedCons just doesn't implement INext, that's what needs fixing.

17:02 squidz: dnolen: okay, thank you for the help, converting to a vector before set seems to quickfix for now.

17:05 sdegutis: Oh, looks like (set!) is what I want.

17:19 asteve: so, 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:19 I'm attempting to upgrade a project from 1.2 t .15.1

17:19 to 1.5.1*

17:20 lein deps :tree shows [org.clojure/clojure "1.5.1"]

17:21 sandbags: hrmm... 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:21 sdegutis: Some of Clojure's features seem like they were invented to make Datomic work, like tagged literals.

17:21 sandbags: i.e. it wants (html [:p "foo"] [:p "bar"]) rather than (html [[:p "foo"] [:p "bar"]])

17:21 technomancy: sdegutis: nonsense; every app needs uuid literals

17:22 hyPiRion: sandbags: You sure about that? I'd think both works just fine

17:22 technomancy: for example, I use uuid literals to identify all the factorials I generate in production

17:22 hyPiRion: *both would work

17:22 sandbags: hyPiRion: 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:23 sdegutis: technomancy: true but do they need to be stored in EDN?

17:23 coventry: asteve: What version of clojure is reported by "lein repl" in that project?

17:23 riley526: sandbags hyPiRion: I remember (html [[:p "asdf"] [:p "qwerty"]]) not working for me either.

17:24 hyPiRion: riley526: yeah, confirmed that it's not working here either.

17:24 asteve: coventry: REPL-y 0.1.9 and Clojure 1.5.1

17:24 sandbags: hyPiRion: https://gist.github.com/mmower/4a5840897b6c0c8f96c5

17:24 technomancy: sdegutis: well technically they don't but the fibonacci ones definitely do

17:25 sdegutis: touché

17:25 sandbags: i guess maybe i could use a macro to do this?

17:25 using the splicing quote?

17:25 is this... a legitimate time to reach for a macro? :)

17:25 riley526: sandbags: I think I ended up using (into [:base-elem] ...) to work around it

17:26 really annoying though

17:26 sandbags: riley526: i'm not sure i understand

17:26 or, rather, i am sure that i don't :)

17:27 the problem seems to be that i can't pass a vector at all

17:27 so i'm not seeing how injecting elements into one gets me further?

17:27 coventry: asteve: Do you get the same error if you run the code in the repl?

17:27 riley526: sandbags: 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:28 asteve: coventry: it's a storm project and I don't fully understand how to run it locally

17:28 riley526: sandbags: doesn't solve the problem, but it's what I ended up with.

17:29 sandbags: ok, thx

17:29 riley526: (html (into [:div] [[:p "abc"] [:p "def"]]))

17:30 gfredericks: "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:30 hyPiRion: sandbags, riley526: There's a better solution, actually. Try out (html (seq [[:p "asdf"] [:p "qwerty"]]))

17:30 coventry: asteve: 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:30 hyPiRion: I knew it was possible, but didn't know the incantation

17:31 riley526: hyPiRion: oh snap

17:31 well there you go

17:31 noprompt: riley526, sandbags you could always use a list instead of a vector and that should also work.

17:31 sandbags: hyPiRion: oh ho ho

17:31 nice, thank you

17:31 noprompt: (list [:el "foo"] [:el "bar"])

17:32 riley526: I'm practically brand new to hiccup and clojure in general, so most of these simple solutions don't come naturally yet.

17:32 noprompt: not as nice as a vector though but i think that should work if i remember the source correctly

17:32 sandbags: hyPiRion's (seq <vec>) seems to work also

17:32 coventry: asteve: Actually, (clojure-version) (it's a function.

17:32 asteve: coventry: thanks, doing that now

17:32 sandbags: which allows me to work with vectors and just convert at the end

17:33 noprompt: oh snap! multi-term! yay, now i (almost) never need to leave emacs.

17:38 rurumate_: 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:40 noprompt: rurumate_: the symbol would be rendered as sudo_make_payment_button in javascript.

17:40 sandbags: okay 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:40 noprompt: sandbags: that's how i started. :)

17:41 sandbags: it feels good not to be defining methods on object and pretending I have functions :)

17:43 noprompt: rurumate_: you also notice symbols like create-user! will be rendered as create_user_BANG_ etc.

17:44 rurumate_: noprompt: yo thanks mate

17:45 noprompt: rurumate_: yo dawg i gacho back bra' ;)

17:45 :

17:45 :P

17:47 rurumate_: seriously though, it's definitely worth looking at the emitted code in with, say, :optimizations :whitespace.

17:50 coventry: Hmm, 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:50 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Compiler is bad!

17:51 coventry: ...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:51 parametrization: howdy all.

17:53 callen: parametrization: hi

17:54 noprompt: callen: hi

17:54 callen: noprompt: hi

17:56 rurumate_: sandbags: are you only pretending to have functions?

17:56 parametrization: I'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:57 noprompt: this looks so awesome http://oldcomputers.net/oldads/80s/apf.jpg

17:57 brehaut: coventry: 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:57 sandbags: rurumate_: unless we're arguing over the semantics of a method as a function with an implied self, yes

17:57 talios: mourning brehaut

17:57 brehaut: hat talios

17:58 s/hat/hey/

17:58 nDuff: parametrization: editor choice is covered in the annual survey, if you want to get an idea of what folks use.

17:58 parametrization: ...emacs _is_ far and away the home of the best tooling, but it's certainly not your only choice.

17:58 parametrization: http://cemerick.com/2012/08/06/results-of-the-2012-state-of-clojure-survey/

17:58 talios: ide sluts all of you ;)

17:58 rurumate_: sandbags: I'd rather have functions

17:58 parametrization: Thanks, I don't know much about this community ATM, I'll click the link and RTFM for a bit, thanks!

17:59 brehaut: coventry: the docs should probably should mention the deftype stuff however

17:59 parametrization: Thanks nDuff.

17:59 sandbags: rurumate_: apparently so would I since, despite my liking Ruby very much, I am here in Clojureland

18:00 rurumate_: sandbags: what drove you away from glorious rubyland?

18:00 coventry: brehaut: 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:01 rurumate_: dont they have functions there?

18:01 sandbags: rurumate_: nothing drove me away, i still like Ruby, but I was drawn to clojure as a Lisp i might actually use

18:01 and by a desire to really understand FP

18:01 noprompt: parametrization: the clojure community is full of good people. your in a safe place.

18:01 sandbags: i've been an OO programmer for longer than i care to remember, maybe i'm feeling the straightjacket was a little too tight

18:02 at least it is now... we'll see over time

18:02 noprompt: parametrization: people here are typically very friendly and helpful.

18:02 sandbags: if Clojure ever gets its "Rails" and the influx of bodies that come with it that'll be an interesting test of community

18:03 parametrization: noprompt I was just telling my team about the lack of condescension up in here :)

18:03 rurumate_: sandbags: I heard they write the opening paren after the function name in non-lisp-land..

18:04 sandbags: rurumate_: in ruby-land they often do not write the paren at all!

18:05 noprompt: sandbags: it'd be a shame if that's what it would take to get people to pay more attention to it.

18:05 rurumate_: I've heard that parens are very rare in pythonland..

18:05 coventry: "Here's zero bucks, kid. Go hit gnu.org and buy yourself a real development system."

18:05 sandbags: noprompt: that's life

18:05 noprompt: gravity is as gravity does

18:06 noprompt: sandbags: 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:06 callen: sandbags: 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:06 sandbags: noprompt: that's not why i think Rails became popular but that's probably off-topic here

18:06 callen: as a result, people just kinda do their thing.

18:06 sandbags: callen: it was already easy to make web apps in Ruby

18:07 callen: they 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:07 sandbags: but 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:07 callen: sandbags: pre-rails Ruby and the current state of Clojure are not comparable at all.

18:07 sandbags: callen: i was not comparing them so that's fine

18:07 callen: Clojure as a community embraces libraries that stand alone. There wasn't a good library ecosystem for making web apps in Ruby back then.

18:08 sandbags: yes sorry maybe i wasn't clear

18:08 callen: it'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:08 sandbags: i wasn't implying that Clojure needs an equivalent to Rails the web framework

18:08 noprompt: sandbags: the down side of text. we can't here your voice or see your facial expressions.

18:08 callen: Ruby web + the usual attendant libraries that come with writing web apps was a wasteland.

18:08 I only used Ruby for dev-ops back then and I could tell it was bad.

18:09 Rails, for all people like to complain about it, brought a lot of lifeblood into the Ruby community.

18:09 sdegutis: Where does set! live?

18:09 callen: sdegutis: in the gateless gate, through which one must pass.

18:09 sandbags: callen: which is more the point i was driving at

18:09 noprompt: (var set!)

18:09 ,(var set!)

18:09 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve var: set! in this context, compiling:(NO_SOURCE_PATH:0:0)>

18:09 brehaut: sdegutis: its a special form

18:09 sdegutis: it exists in the compiler

18:09 callen: sandbags: my point is that the conditions that precipitated and necessitated Rails do not exist in the Clojure community.

18:09 sdegutis: brehaut: oh, neat.

18:09 sandbags: and what the side-effects of that life-blood might be

18:10 noprompt: brehaut: well that's good to know. :)

18:10 sdegutis: And (set!) works just like (binding)?

18:10 callen: given that the conditions for such are nonexistent, it's not a very interesting question at all

18:10 sandbags: yes okay, let's leave it there

18:10 sdegutis: With the obvious difference of being side-effecty.

18:10 asteve: ClassCastException java.lang.Class cannot be cast to clojure.lang.IFn user/eval1144 (NO_SOURCE_FILE:1)

18:10 so, where to begin with this one?

18:10 brehaut: sandbags: heres some tools in clojure that draw in people in the way rails did: core.logic, core.async, clojurescript, datomic…

18:11 callen: brehaut: yep. Datomic is why we're getting Clojure at my company.

18:11 sandbags: brehaut: i don't have any numbers but i'd find that surprising

18:11 callen: sandbags: how long have you been writing Clojure?

18:11 sandbags: but i'm here and i have no skin in this game so :)

18:11 brehaut: sandbags: theres also all the stuff in clojure core, persistent structures, STM, etc etc

18:12 noprompt: callen: "lifebood"

18:12 brehaut: sandbags: dont confuse a lack of library for _your_ niche interest for everyone elses

18:12 sandbags: i suspect we're talking at cross-purposes

18:12 brehaut: ?

18:12 callen: sandbags: how long have you been writing Clojure?

18:12 sandbags: callen: on and off i guess about 3 months

18:13 callen: sandbags: yeah, best to let this conversation die then.

18:13 sandbags: you don't have a frame of reference for where the community's been or where it's headed.

18:13 sandbags: fine by me

18:13 brehaut: sandbags: 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:13 noprompt: sandbags: yes let us drain the so-called "lifeblood" from the matter.

18:13 callen: brehaut: stop. seriously.

18:13 brehaut: callen: you are right. i should be working

18:14 callen: brehaut: I don't care what you do alternately, I'd just prefer to avoid bikeshedding in this channel if possible.

18:16 noprompt: c'mon you guys. let's not fuss. we just told that other guy that we are nice people.

18:16 sdegutis: One great thing about Clojure is that I understand everything that's going on.

18:16 noprompt: you're making making me look liar.

18:16 lol

18:16 sdegutis: I love that about Clojure code I read and write.

18:16 callen: sdegutis: really?

18:16 rasmusto: sdegutis: everything is a strong word

18:16 sdegutis: When I see a given function, I usually don't have to dive very deep to know what it's doing.

18:17 riley526: ah, "referential transparency"

18:17 callen: you'd be surprised how often a library has dark corners that aren't referentially transparent.

18:17 sdegutis: I mean besides domain-specific functions. If it uses those, there's obviously no way of knowing what it's doing without digging.

18:18 But I love that the vast majority of code uses functions straight out of clojure.core that I already know.

18:18 sandbags: sdegutis: do you mean that there's less that is implicit in your code?

18:19 noprompt: callen: yes, i've seen these "dark corners" you speak of. even the syntax highlighting changes.

18:19 rasmusto: sdegutis: I guess "knowing how the functions are used" is a bit different than knowing everything that's going on under the hood

18:19 sdegutis: And 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:19 callen: noprompt: libraries often have to commit deeper evils in order to be nice to use.

18:20 noprompt: callen: yes. like loop/recur, transients, and the dreaded ^:dynamic *var*.

18:21 so dark are these that poison the hearts of men.

18:21 callen: loop/recur isn't evil.

18:21 transients aren't evil either, they just require a good reason to be used.

18:21 riley526: why is loop/recur evil?

18:21 callen: noprompt: you lack imagination. I could show you such wonderful horrors.

18:21 riley526: it's not.

18:21 I just said it isn't.

18:21 technomancy: riley526: it's low-level

18:21 it doesn't belong in application-level logic

18:22 noprompt: riley526: it's not. i'm just heckling callen.

18:22 riley526: I can see the low-level argument

18:22 callen: what constitutes low-level/high-level necessary/unnecessary depends on what you're writing.

18:22 If you're aphyr or ztellman, you probably have a good reason.

18:22 if you're not, then you don't.

18:23 really simple actually.

18:23 riley526: a noob clojurian like myself will reach for it all the time though

18:23 unfortunately.

18:23 callen: that hasn't been my experience.

18:23 * noprompt loves when people take it "seriously"

18:23 ztellman: as much fun as it is to be the poster boy for questionable Clojure usage

18:23 callen: ztellman: but you have an excuse, so it's okay.

18:23 ztellman: I'd tend towards the answer of use loop/recur when it's simpler than function composition

18:23 which it is, sometimes

18:23 technomancy: loop/recur means either "I need crazy perf" or "I haven't thought through my problem in terms of sequences"

18:24 or "I'm doing I/O" maybe

18:24 noprompt: riley526: no need to talk down about yourself. use the best tools in your toolbox. nothing wrong with doing what you know best.

18:24 ztellman: sometimes it's more indirect to express operations in terms of sequence operators

18:24 noprompt: riley526: unless of course that's, you know, meth or something.

18:24 ztellman: technomancy: do you disagree?

18:24 technomancy: ztellman: can't say I've had that experience

18:24 noprompt: technomancy: "crazy perf". i love it.

18:24 riley526: noprompt: lol, sure. I'm just recognizing inexperience.

18:25 technomancy: but I've been out of the loop for a while

18:25 ztellman: technomancy: especially when you're updating an accumulator that drives behavior

18:25 technomancy: ztellman: usually the source of updates can be expressed as a sequence though

18:25 like having a board game as reducing a board over a seq of moves

18:25 even if the moves haven't happened yet

18:26 noprompt: i could definitely use some tips on how to eliminate loop/recur stuff with the new garden version i'm working on. :S

18:26 technomancy: (defn go [] (reduce play (init-board) (interleave player-1-moves player-2-moves)))

18:26 (though you can't actually do that in go because of ko)

18:27 ztellman: haha, I'm dreading going back to my go implementation

18:27 that code got messy in places

18:27 mostly for performance reasons, though

18:27 noprompt: technomancy: what would you call loop/recur + transients? "perf madness"?

18:28 technomancy: noprompt: the silver lining of the cloud that is JVM startup time is that I almost never need to care about perf in leiningen

18:28 any optimizations I make will have the looming spectre of startup time shadowing their glory

18:28 dissipate__: technomancy: time to go to another language?

18:29 noncom: noprompt: i had these thoughts. i would call it "use java here".

18:29 technomancy: I can count on one finger the number of times I've turned on *warn-on-reflection*

18:29 dissipate__: well, yes: https://github.com/technomancy/grenchman/blob/master/grench.ml

18:30 dissipate__: technomancy: oh hell no. why not haskell?

18:30 technomancy: dissipate__: https://mobile.twitter.com/technomancy/status/367661164433383424?p=v

18:31 TimMc: pffft

18:31 dissipate__: technomancy: you got me there. :P

18:32 technomancy: ocaml lets you distribute smaller native binaries too, but unfortunately that's only true if you don't use the Jane Street libs

18:32 this program is nearly all IO anyway

18:35 sdegutis: What'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:37 technomancy: OCaml is kinda crappy at JSON actually

18:37 brehaut: technomancy: thats ok, most languages are

18:37 hiredman: needs type classes

18:40 s4muel: Hi 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:41 technomancy: sdegutis: some of that depends on whether you can assume an existing runtime

18:41 s4muel: it is the result i want, it just seems kind of messy. But then again, I'm new here.

18:43 technomancy: sdegutis: 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:45 noprompt: s4muel: i don't see anything "wrong" with that. of course it really depends on the problem you are trying to solve.

18:46 s4muel: if you're using 1.5.1+ you can use mapv instead of the (vec (map combo

18:46 dnolen: s4muel: why is the latter data desirable over the former in your case?

18:47 s4muel: noprompt: thanks, that's the kind of thing i was looking for.

18:48 sandbags: thanks for all the help earlier & conversation folks. g'night

18:51 s4muel: dnolen: 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:52 dnolen: s4muel: so you want to access your data structure via numeric indexes?

18:52 s4muel: Although it might be better to create another map.

18:53 dnolen: s4muel: yeah that's what I was wondering

18:53 s4muel: I just thought about that -- I was focusing more on the destructuring of the original response

18:53 Thanks :)

19:32 powrtoc: I'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:32 any ideas?

19:32 does core.async handle interrupts/threads properly?

20:03 lgs32a: did anybody here get clojurec to work?

20:04 e. g. pass the tests?

20:05 llambda: what's the best way to reference a local clojure project as a dep in another project? preferably via lein :)

20:05 lgs32a: llambda: lein install

20:05 llambda: cool, thanks

20:05 lgs32a: then simply use it in project.clj under dependencies

20:06 llambda: also 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:06 clone and do the same or is there an easier way?

20:06 lgs32a: hmmmz a maven repository?

20:15 coventry: llambda: 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:24 llambda: coventry: thank you, that's very helpful!

20:28 squidz: something 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:29 what 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:30 something 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:32 brehaut: ,(let [l [{:key "a" :val "a"} {:key "b" :val "b"} {:key "c" :val "c"}]] (for [a l b l] [a b]))

20:32 clojurebot: ([{: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:33 brehaut: ,(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:33 clojurebot: ([{: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:34 squidz: brehaut: yes that works when working with clojure datastructes but not clojurescript structures

20:34 i mean javascript objects

20:35 brehaut: squidz: you want javascript objects inside the seq?

20:36 noprompt: squidz: you could always use js->clj or write a custom macro. worse you could extend ILookup, etc to object.

20:36 squidz: yes the input are js objects and the output pairs need to be too

20:37 I had exaclty the example you have, but js-objects seem to be tricker with equality

20:37 noprompt: squidz: also remember you have the google closure libraries at your disposal too like goog.object etc.

20:38 squidz: I 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:49 lgs32a: does somebody know a librabry that can parse http-link escapes like %20 to what they actually mean, e.g. space

20:52 nevermind, remembering .net.URI

20:55 coventry: ,(do (defn & []) (defn silly-buggers [& args] [& args]) (silly-buggers))

20:55 clojurebot: #<Exception java.lang.Exception: SANBOX DENIED>

20:56 callen: "SANBOX"

21:00 seangrov`: callen: It will never be fixed.

21:01 yedi: anyone 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:01 callen: seangrov`: I actually submitted a PR to fix it.

21:01 technomancy: use bcrypt

21:01 callen: seangrov`: it got merged. it was never deployed.

21:02 technomancy: ^ the extent of my knowledge

21:02 callen: yedi: use bcrypt. don't store important information in cookies without encryption.

21:02 if you want to be really elite use scrypt.

21:02 yedi: scrypt works too right?

21:02 oh word

21:02 technomancy: delegate to another site with oauth if you can get away with it

21:03 callen: I...wouldn't do that.

21:03 users tend to hate you if you force oauth on them without it being purposeful.

21:03 there needs to be a reason other than, "I refuse to write 4 lines of code for a login functionality"

21:05 yedi: 4 lines of code is a little bit of an understatement,,,

21:05 coventry: Yeah, there's the password reset functionality.

21:16 tufflax: Is there a nicer way of doing (if x (conj xs x) xs)? x can never be false, just nil

21:20 bbloom: tufflax: that seems nice enough to me, but what about (cond-> xs x (conj x))

21:22 tufflax: bbloom: yeah maybe it is nice enough :p

21:22 bbloom: tufflax: i frequently define utility functions like these: (def conjs (fnil conj #{})) and (def conjv (fnil conj []))

21:23 if you need that a bunch in one file, just make conjx or something

21:23 technomancy: callen: what about "I refuse to add a database to accommodate people who hate github"?

21:25 callen: technomancy: punish them by making your database an append log on disk.

21:25 a naive implementation.

21:25 technomancy: the more they use the service, the slower it gets (scanning the append log)

21:25 if they complain? explain the above.

21:25 yedi: is that a challenge?

21:26 yedi: because if it's a challenge...

21:26 * callen cracks knuckles and grins

21:31 tufflax: bbloom: ok but that does not really solve my current problem, unless im missing something... :p

21:31 bbloom: tufflax: 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:31 tufflax: don't be afraid to factor out little functions even if they are only useful once :-)

21:32 tufflax: yeah i do that, usually in let/letfn though

21:32 xeqi: callen: I am interested to see how far you get in a user system with 4 lines

21:37 callen: xeqi: I could make a minimally functional login/auth, logout, session mgmt system for a web app in 4 lines.

21:37 xeqi: callen: password reset, password change, username change ?

21:38 + views

21:39 callen: don't move the goal post.

21:39 here's a better proposal, "you have 4 lines. How much of a user mgmt system can you implement?"

21:39 xeqi: hmm, does oauth give those?

21:39 callen: not really, no.

21:39 it's just login/auth @ Oauth2

21:39 and I can replace that in 1 or 2 lines

21:40 I can do logout and session management in 1 or 2 more lines.

21:40 I think I could certainly replace OAuth2 in 4 lines of code for a single web app.

21:40 easy-peesy.

21:40 and by replace, I don't mean, "emulate the API", I mean, functionally replace the purpose of it with an in-house login/auth

21:41 technomancy: you get password reset with oauth

21:41 you even get 2fa now with github oauth

21:41 callen: that's...what...no.

21:41 that

21:41 is not oauth.

21:41 that's vendor specific stuff related to their own account management

21:41 oauth2 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:42 all 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:42 I'm going to tweet that now so people can understand OAuth.

21:43 -12, fuck.

21:43 sdegutis: technomancy: noted, thanks

21:43 xeqi: .. so its an API that hooks into a system that already has password reset and change and views built

21:44 callen: xeqi: correctamunde.

21:44 but the "purpose" of it is login/auth specifically

21:44 because you're authenticating the person

21:44 but you still have to manage the sessions and logout even if you use OAuth.

21:44 xeqi: certainly seems like the goal posts for an equivalent system should include those

21:44 technomancy: callen: if you use oauth from github, you get those benefits

21:45 * callen plucks eyeballs out and throws one apiece at technomancy and xeqi in spite

21:46 callen: xeqi: you realize that because Clojure is a Lisp, I can ride the 4 line limitation straight to hell right?

21:46 technomancy: callen: no column limitation you mean? =P

21:47 xeqi: callen: you could do that with any language with multi statements per line

21:47 technomancy: ruby has a 5-line wiki

21:47 (one of the lines is a shebang)

21:48 callen: http://viewsourcecode.org/why/redhanded/bits/batsmansFiveLineWiki.html

21:48 xeqi: technomancy: no `Redmine.new` and poof I have a wiki? awww

21:51 yedi: callen: well obviously

21:52 brehaut: technomancy: http://www.c2.com/cgi/wiki?ShortestWikiContest

21:52 technomancy: no surprises but perl has 4 lines including shebang

21:53 asdf__: question for you all. Is there a quick/simple way to replace nils in a list with zeros?

21:54 brehaut: ,(map #(if (nil? %) 0 %) [1 nil 2 nil 3])

21:54 clojurebot: (1 0 2 0 3)

21:54 technomancy: brehaut: well hello mister fancy pants

21:55 brehaut: asdf__: but for bonus marks ##(map (fnil identity 0) [1 nil 2 nil 3])

21:55 lazybot: ⇒ (1 0 2 0 3)

21:55 asdf__: 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:56 brehaut: ,(remove nil? [1 nil 2 nil])

21:56 clojurebot: (1 2)

21:57 brehaut: im not sure what you mean by map multiply

21:57 asdf__: 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:58 brehaut: asdf__: fnil again

21:58 ,(apply + (map (fnil * 0 0) [1 nil 2 nil] [5 6 1 2])))

21:58 clojurebot: 7

21:59 brehaut: ,(doc fnil)

21:59 clojurebot: "([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:00 asdf__: ahh look at that. awesome

22:01 quick thing then. difference between apply and reduce

22:01 brehaut: apply happens to be a tiny bit smarter with variadic functions

22:02 the seq gets marshalled into something something varargs rather than something else wheres amalloy to explain it

22:02 gfredericks: clojurebot: where is amalloy to explain it

22:02 clojurebot: c'est bon!

22:07 asdf__: one more thing. you guys are always really helpful. way easier to ask questions here than google/stack overflow.

22:16 gfredericks: (inc #clojure)

22:16 lazybot: ⇒ 5

22:30 amalloy: brehaut: wut

22:30 brehaut: amalloy: apply vs reduce for functions like +

22:30 gfredericks: amalloy: thank god you're here!

22:31 brehaut: amalloy: i know thres a reason, but ive comepletely mangled it in my remembering

22:31 amalloy: *shrug* i mean, reduce is marginally faster for +, because apply just delegates to reduce

22:31 but for str, apply is way way faster than reduce

22:32 brehaut: oh. well there you go. i auto cargo culted and got it wrong

22:32 callen: I thought apply was really slow in some cases for some reason.

22:36 john2x: ,(doc apply)

22:37 clojurebot: "([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:37 Scriptor: is it largely because apply handles multiple arities?

22:37 john2x: ,(doc reduce)

22:37 clojurebot: "([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:37 Scriptor: up to 4 or so arguments before the varargs

22:42 bja: I think ring+compojure+ring-edn is making me lazy

22:45 callen: bja: tragedy.

23:01 sdegutis: technomancy: found a real life picture of Leiningen: https://www.dropbox.com/s/4m4l77gfoykmp0m/leiningen.jpg

23:06 fkey: (for [x [1 2 3 4]] ((fn [y] (* y)) x)) works , but

23:06 (for [x [1 2 3 4]] ((fn [y] (.log js/console "test")) x)) doesn't...why is that so?

23:07 coventry: for returns a lazy sequence. Realize it with doall.

23:08 gfredericks: or use doseq instead

23:09 fkey: if i replace for with doseq, it logs to console only item, and never gain

23:09 is doseq lazy too?

23:09 sdegutis: ,(doc doseq)

23:09 clojurebot: "([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:10 xeqi: doseq is not lazy

23:11 coventry: fkey: Does the console avoid printing repeat messages? You might try logging a message which varies with x.

23:11 fkey: coventry: will try that

23:11 coventry: i guess firebug was hiding some info from me, thanks

23:13 xeqi: fkey: 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:14 fkey: xeqi: thanks, i originally tried that but was confused why the logging wasn't working heh

23:27 coventry: What'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:27 Don't need to understand this for my current project, but I am curious.

23:27 yedi: forgot clabango doesn't support else

23:27 really need to move to selmer

23:40 ddellacosta: I'm curious what people took away from Alex Miller's piece: http://tech.puredanger.com/2013/08/31/clojure-and-testing/

23:40 I've been thinking about testing in Clojure a lot lately because I have a strong feeling that "I'm not doing it right."

23:41 but it could be because the system I'm building now is badly designed

23:41 which complicates my tests.

Logging service provided by n01se.net