#clojure log - Sep 01 2014

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

2:28 sm0ke: so if i am building this nested map {:a {:b {:c 1 :d x}}}, i want if x is nil its not assoc'd to the map

2:28 is there a nice way to do this

2:31 TEttinger: ,(let [m {:a {:b {:c 1}}} x nil] (if (nil? x) m (update-in m [:a :b :d] x)))

2:31 clojurebot: {:a {:b {:c 1}}}

2:31 TEttinger: ,(let [m {:a {:b {:c 1}}} x 2] (if (nil? x) m (update-in m [:a :b :d] x)))

2:31 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

2:31 TEttinger: ,(let [m {:a {:b {:c 1}}} x 2] (if (nil? x) m (update-in m [:a :b :d] (constantly x))))

2:31 clojurebot: {:a {:b {:d 2, :c 1}}}

2:31 sm0ke: yes thats the obvious way, i was looking something `easy`

2:32 TEttinger: well I imagine it wouldn't be hard to make that into a more general function. the update-in is the tricky bit

2:33 closest thing I can think of is when-let

2:33 (doc when-let)

2:33 clojurebot: "([bindings & body]); bindings => binding-form test When test is true, evaluates body with binding-form bound to the value of test"

2:33 sm0ke: yes yes, but i want this to work on arbitary data e.g.

2:33 {:a {:b {:c [1 2 x]}}}

2:33 i want to eliminate that x

2:34 TEttinger: complex nesting is not the kind of thing there's pre-written solutions for

2:34 update-in is as close as it gets

2:34 I could be wrong and amalloy swoops in with a half-of-one-liner

2:35 sm0ke: i think it is impossible

2:35 TEttinger: well you haven't really described what you want

2:35 sm0ke: what i want is something like compile time with consitions on runtime

2:35 condition*

2:36 TEttinger: do you want to be able to replace any instances of some variable, like 'x , with a value regardless of where it is?

2:37 sm0ke: i just want an prettier alternative to what you did, (let [m {:a {:b {:c 1}}} x 2] (if (nil? x) m (update-in m [:a :b :d] x)))

2:37 TEttinger: ,(count "(if (nil? x) m (update-in m [:a :b :d] x))")

2:37 clojurebot: 42

2:38 sm0ke: you are ignoring the let form

2:38 TEttinger: because that's just your predefined stuff

2:38 that's stuff you would pass in

2:38 ,(def m {:a {:b {:c 1}}})

2:38 clojurebot: #'sandbox/m

2:39 sm0ke: what if there was something like {:a {:b {:c 1 **-x :d x}}}

2:39 TEttinger: ,(def x 2)

2:39 clojurebot: #'sandbox/x

2:39 TEttinger: ,(if (nil? x) m (update-in m [:a :b :d] x))

2:39 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

2:39 sm0ke: **- is magic condition which ignores depending on x

2:39 :P

2:39 TEttinger: ,(if (nil? x) m (update-in m [:a :b :d] (constantly x)))

2:39 clojurebot: {:a {:b {:c 1, :d 2}}}

2:39 TEttinger: well uh your map has 5 items

2:40 sm0ke: yes **-x is a reader macro

2:40 TEttinger: ok, you could probably do that yes. reader macros are kinda discouraged...

2:40 I'm thinking of reader literals

2:40 which are not recommended in libraries

2:40 sm0ke: #only/if

2:41 i am not sure if even that would work

2:41 it is impossible to do this {:a {:b {:c 1 #only/if :d x}}}

2:41 TEttinger: it should be. hang on

2:42 ,{:a {:b {:c 1 #_ :d #_ x}}}

2:42 clojurebot: {:a {:b {:c 1}}}

2:42 TEttinger: so you can already ignore forms, you just want to do it selectively

2:42 sm0ke: yes my first though was also using (comment)

2:43 TEttinger: which returns nil, for some reason...

2:43 sm0ke: ,{:a {:b {:c 1 (if false [:d 2] (comment))}}}

2:43 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

2:43 sm0ke: wow stupid

2:44 TEttinger: it's true though

2:44 that's a key, [:d 2]

2:44 sm0ke: but it has to be a compile time thing you see? but (if x..) is a runtime thing

2:45 cant be done!

2:47 TEttinger: yeah, I think because you're trying to do it inside the map {} literal

2:47 sm0ke: yes we would need a special macro for [] {} etc to do this

2:47 TEttinger: if is a macro, and I admit I'm not an expert on macros

2:48 sm0ke: ugh, i am going back to if's and let's

2:49 TEttinger: yes, if is what you should use here

2:49 all other solutions are much more hackish

2:52 sm0ke: so all that we need is this (runtime-to-compiletime-if x [:d 2]) this evaluates x during runtime and spats :d 2 (flattening them) for the compiler

2:52 which makes no sense

2:53 yay! I just wasted your 15 minutes

3:10 SagiCZ1: anyone remembers how do i access this channels logs?

3:11 beamso: http://logs.lazybot.org/irc.freenode.net/%23clojure/2014-09-01.txt

3:12 SagiCZ1: beamso: thank you

3:13 i need couple more hours back

4:53 JL235: Has anyone got any experience with clojure-clr?

4:53 I am thinking of using it

4:53 I have a .net project and thinking of rebuilding it with clojure (as I also want to get into Lisp too)

4:55 clgv: JL235: what is stopping you from trying it?

5:15 JL235: nothing

5:15 but I don't want to invest time moving a project over to something that may have a lot of warts

5:15 not when I could go with something else instead

5:15 so just asking around on people's experiences

5:18 clgv: JL235: well, before migrating a project you need to learn the language. Hence, I asked what is stopping you from trying out clojure and start learning the basics?

5:24 JL235: I am not asking in regards to learning the language

5:25 clgv: JL235: what are you asking then? the more specific the question the likelier you get a helpful answer

5:26 JL235: "Has anyone got any experience with clojure-clr?"

5:30 maxthoursie: JL235: I've tried to use it, but while core is there, lot's of libraries aren't. I ended up going with jvm clojure instead

5:37 jyfl987: hi can anyone give me some example showing parsing weblog file , the filename should be given by cmdline

5:40 riffraff: hi everyone

5:41 I'm tryint to add test.check tests to my project and I'd like to have them run as normal tests as per clojure.test

5:41 AFAIU I shoiuld use defspec, but I get a Unable to resolve symbol: defspec in this context

5:42 any ideas of what I'm doing wrong? Sorry if' it's a silly question, I'm a newbie :/

5:44 JL235: thanks maxthoursie

5:44 riffraff: ah I found it in another namespace maybe

6:13 clgv: riffraff: why not deftest?

6:13 riffraff: it was my understanding defspec was the preferred way to use test.check with clojure.test

6:13 clgv: riffraff: ah defspec is part of test.check

6:13 riffraff: yeah

6:13 the name is somewhat confusing to me as it seems to refer to some BDD framework

6:13 clgv: from the tests in test. heck it seems to be the way to go

6:13 riffraff: yes I got it working now

6:13 the trick was that it's defined in clojure.test.check.clojure-test

6:13 clgv: for future readers, it is in clojure.test.check.clojure-test

6:13 riffraff: but this is not called out in the readme. As a noob I assumed I was doing something stupid with requires :)

6:13 clgv: yeah, there could be more documentation.

6:13 I am just fiddeling with recursive generators

6:16 riffraff: err, another silly question: given "lein repl" where my project.clj has org.clojure/test.check in the dependencies, should (require '[clojure.test.check :as tc])

6:16 work ?

6:20 clgv: riffraff: yes, it should

6:20 riffraff: do you do any profile magic?

6:20 riffraff: not that I am aware of

6:21 clgv: did you restart the repl after adding the dependency?

6:23 riffraff: the one I just opend yes

6:23 not sure if there is some daemin process I need to restart too

6:24 clgv: riffraff: no. requiring should work then

6:25 replace "should" with "must"

6:26 riffraff: eh :)

6:29 ah I think it _is working, but I was looking at it wrongly

6:30 basically, trying to see if the symbol "tc" was bound to something (by typing "tc" in the repl)

6:30 but it's not, while tc/quick-check instead is

6:30 I think I need to study this namespacing thing a bit more

6:30 thanks anyway

6:51 clgv: riffraff: ah ok.

6:52 ,(require '[clojure.string :as str])

6:52 clojurebot: nil

6:52 clgv: ,(keys (ns-aliases *ns*))

6:52 clojurebot: (str)

6:52 clgv: riffraff: that's a way to check the alias ^^

6:52 riffraff: awesome, thanks

6:53 clgv: ,((ns-aliases *ns*) 'str)

6:53 clojurebot: #<Namespace clojure.string>

6:53 clgv: ^^ to see where it maps to

6:56 martinklepsch: when evaling (println "something") in cider, is there a buffer where I can see the result?

6:56 ah, nevermind

6:56 the cider-repl buffer :)

7:30 SagiCZ1: if i have a non-atom list of atoms can i see their changes?

7:34 clgv: SagiCZ1: example?

7:35 SagiCZ1: (def a (atom 0)), (def b (atom 1)), (def v [a b]), .. now i keep the reference to "v" i can swap! the atoms in it right?

7:37 noidi: yes, but not atomically :)

7:37 SagiCZ1: noidi: elaborate?

7:38 clgv: SagiCZ1: you cant guarantee any consistence between the two atoms

7:39 SagiCZ1: your options are to have the vector within an atom or to use references instead of the atoms

7:39 noidi: SagiCZ1, say both atoms start at 0 and you want to `inc` them. an observer may observe a world in which one atom has the value 1 and the other 0

7:39 clgv: SagiCZ1: btw your usage of def for `a` and `b` is alarming

7:46 SagiCZ1: why is alarming?

7:53 (ns my-ns (:require [ui]))

7:53 this says it could not locate ui__init.class but i have the ui namespace in the same folder, whats wrong?

7:56 llasram: SagiCZ1: namespaces are always absolute, never relative

7:57 SagiCZ1: thank you, it works now

7:58 clgv: SagiCZ1: because `def` is only intended for *global* variables

7:59 SagiCZ1: clgv: these are supposed to hold game's state and i read that game state should be global and immutable

8:00 lq: ls

8:00 lazybot: bin etc home lib lost+found media mnt opt proc root sbin sys usr var

8:01 llasram: SagiCZ1: Yeah, but you don't need two top-level references to the same object. E.g., just: (def game-state [(atom 0) (atom 0)])

8:01 (or whatever)

8:02 SagiCZ1: oh yes ive already changed that.. it was just for the example.. thank you though

8:02 clgv: SagiCZ1: what llasram said ^^

8:04 SagiCZ1: I think the decision between game state as global variable or game state as function argument is not that clear as you state

8:04 SagiCZ1: clgv: its the only that makes sense to me.. i cant wrap my head around passing game state around 20 functions

8:05 llasram: SagiCZ1: And yet it has a lot of benefits

8:05 clgv: SagiCZ1: that way you are tempted to have no pure functions at all

8:06 SagiCZ1: if i try to use only pure functions i cant progress at all.. do you have any examples of very simple games with pure functions?

8:06 clgv: SagiCZ1: pure functions are "easy" to test

8:06 llasram: At my company we started off with several things that it seemed to "make sense" would just be global state, like configuration

8:07 And we've realized it was pretty much all a terrible idea, which has made code much harder to test, and are moving to pure-as-possible functions for everything

8:07 SagiCZ1: llasram: i understand all the advantages of pure functions.. which does not make me able to write them

8:07 clgv: SagiCZ1: well, you will have at least one function that holds the atom, e.g. the main game loop

8:07 llasram: SagiCZ1: Why is it harder? You just have an extra first argument to your functions which is the game state

8:08 lvh_: is there a codecs library I'm missing? I need urlsafe base64; the only one I can find is inside buddy

8:08 and dragging in all of buddy for 10 lines or so seems silly

8:08 llasram: lvh_: Apache Commons?

8:08 lvh_: (as does copying those 10 lines)

8:08 lvh: llasram: does that have urlsafe base64? I thought it didn't, I'll double check

8:08 llasram: Oh, maybe not. I just assumed it would

8:08 clgv: lvh_: isn't there some clojurewerkz lib for URLs that is able to do that?

8:08 llasram: What makes normal base64 not URL-safe?

8:09 lvh: llasram: wait, you're right, it does :)

8:09 llasram: cool

8:09 lvh: clgv: that'd be great!

8:09 SagiCZ1: the thing is.. i am using swing for rendering, i.e. paintComopnent method which has fixed amount of arguments.. how could i pass the state in there?

8:09 lvh: clgv: *looks*

8:09 llasram: some parts of the alphabet

8:09 llasram: + and /, specifically

8:09 llasram: Ah, of course

8:10 clgv: SagiCZ1: do you use seesaw?

8:10 SagiCZ1: clgv: yes

8:11 lvh: clgv: there's https://github.com/clojurewerkz/route-one, but it doesn't appear to know anything about base64.

8:11 clgv: SagiCZ1: well, you can easily build closures as paint handlers, that close over the game state atom. on each paint call you deref the atom

8:11 SagiCZ1: clgv: either the entities i want to render must be global or the canvas i want to paint on must be global

8:12 yeah using clojure while not understanding closures sounds like a terrible idea

8:13 clgv: SagiCZ1: the functions that do the actual painting cant be pure of course, but the game logic that updates the state can be

8:14 SagiCZ1: they cant be pure because the fact that they actually "paint on screen" is a side-effect right?

8:15 clgv: lvh: the contrib lib data.codec has base64 encoding but it's also a bigger dependency...

8:16 SagiCZ1: yeah. but functions that determine how something needs to be painted (e.g. color dependend on several state values) can be pure

8:17 SagiCZ1: clgv: could u write a pseudocode example of this please? "well, you can easily build closures as paint handlers, that close over the game state atom. on each paint call you deref the atom"

8:20 clgv: SagiCZ1: here is the example how to add a paint handler https://github.com/daveray/seesaw/blob/master/test/seesaw/test/examples/paintable.clj#L31

8:22 SagiCZ1: i am using that.. but the "draw-a-red-x" is not "closing over" anything is it?

8:23 clgv: SagiCZ1: in the function creating your gui you could do something like (defn create-gui [game-state-atom, ...] (<CANVAS-COMPONENT> ... :paint (fn [component, graphics] (let [game-state @game-state] ....paint...))))

8:23 SagiCZ1: clgv: now i see it.. perfect!

8:23 clgv: SagiCZ1: just replace <CANVAS-COMPONENT> with whatever you use as canvas

8:24 change "@game-state" to "@game-state-atom"

8:24 SagiCZ1: yeah.. no the atom does not have to be global

8:24 *now

8:29 lvh: Is there a ring/compjure thing that lets me say "this part of the URL is a base64 thing; please give me the decoded version"

8:36 SagiCZ1: clgv: back your example.. is it possible to create the inner function somewhere else for clarity? or it has to be nested to access the atom?

8:38 clgv: maybe i should have a "factory-function" that can output a function with the closure?

8:41 jeffterrell: lvh: I found ring.util.codec/base64-{en,de}code here: http://mmcgrana.github.io/ring/ring.util.codec.html

8:41 lvh: Does that work for you?

8:41 lvh: jeffterrell: yeah, me too. Not urlsafe though.

8:41 jeffterrell: (also doesn't automagically do the encoding btu I can live with that

8:43 jeffterrell: Fair enough.

8:44 lvh: I wish clojure.string.trim let me specify which chars I wanted to trim

8:46 SagiCZ1: i would like to call a function n times to generate a list of n items, how do i do that?

8:46 hyPiRion: (repeatedly n fun)

8:46 it's lazy though, so be aware of that

8:46 ,(repeatedly 10 rand)

8:46 clojurebot: (0.5949458375138312 0.08279190123529145 0.14265751227133672 0.07628975550512085 0.7772873079770356 ...)

8:47 SagiCZ1: hyPiRion: thats what i want

8:47 ty

8:48 ,(repeatedly 4 #(0))

8:48 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

8:48 SagiCZ1: why this doesnt work though?

8:49 ,(repeatedly 4 (fn [] 0))

8:49 clojurebot: (0 0 0 0)

8:49 SagiCZ1: and now it does??

8:49 lazybot: SagiCZ1: Definitely not.

8:50 SagiCZ1: ,(repeatedly 4 #((0)))

8:50 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

8:50 hyPiRion: SagiCZ1: What is (0) ?

8:50 SagiCZ1: i just want a function that returns 0

8:50 this is not correct? #(0) ?

8:50 clgv: SagiCZ1: (constantly 0)

8:50 r4vi: (0) is trying to function call a Long

8:50 hyPiRion: If you want a constant you could use (repeat 4 0), btw

8:51 clgv: ,(read-string "#(0)")

8:51 clojurebot: (fn* [] (0))

8:51 clgv: SagiCZ1: ^^ that's why

8:51 riffraff: (repeatedly 4 #( 0 ) ) wouldn't work either though, why?

8:51 clgv: riffraff: see above

8:51 SagiCZ1: it wraps it with another set of braces

8:51 hyPiRion: ,'#(0)

8:51 clojurebot: (fn* [] (0))

8:51 riffraff: ahihi, got it

8:51 clgv: hyPiRion: uhh shortcut :D

8:52 SagiCZ1: ,(constanly rand)

8:52 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: constanly in this context, compiling:(NO_SOURCE_PATH:0:0)>

8:52 SagiCZ1: ,(constantly rand)

8:52 clojurebot: #<core$constantly$fn__4178 clojure.core$constantly$fn__4178@147fc78>

8:52 SagiCZ1: ,((constantly rand))

8:52 clojurebot: #<core$rand clojure.core$rand@15e8c9d>

8:52 hyPiRion: that's a function returning the function rand all the time

8:52 SagiCZ1: ,((constantly (rand)))

8:52 clojurebot: 0.3298967693738979

8:53 SagiCZ1: ,(repeatedly 5 #(constantly (rand)))

8:53 clojurebot: (#<core$constantly$fn__4178 clojure.core$constantly$fn__4178@b873c> #<core$constantly$fn__4178 clojure.core$constantly$fn__4178@dbb0af> #<core$constantly$fn__4178 clojure.core$constantly$fn__4178@12cea05> #<core$constantly$fn__4178 clojure.core$constantly$fn__4178@1b7fb2c> #<core$constantly$fn__4178 clojure.core$constantly$fn__4178@1cb30a4>)

8:53 SagiCZ1: nevermind

8:53 clgv: ,(repeatedly 5 (constantly (rand)))

8:53 clojurebot: (0.17791487825993624 0.17791487825993624 0.17791487825993624 0.17791487825993624 0.17791487825993624)

8:53 clgv: SagiCZ1: no idea why you want it that complicated but that works ^^

8:54 ,(repeat 5 (rand))

8:54 clojurebot: (0.9761251033774431 0.9761251033774431 0.9761251033774431 0.9761251033774431 0.9761251033774431)

8:54 clgv: SagiCZ1: same effect ^^

8:54 SagiCZ1: clgv: ^^ just playing around

8:55 so is there a nicer way to do exactly this?

8:55 ,(repeatedly 4 (constantly {:a 0 :b (rand)}))

8:55 clojurebot: ({:a 0, :b 0.49531751143064073} {:a 0, :b 0.49531751143064073} {:a 0, :b 0.49531751143064073} {:a 0, :b 0.49531751143064073})

8:56 SagiCZ1: ,(repeat 2 {:a 0 :b (rand)})

8:56 clojurebot: ({:a 0, :b 0.8084007871336014} {:a 0, :b 0.8084007871336014})

8:56 SagiCZ1: got it

9:02 hyPiRion: you want (rand) to be the same value for each item? Asking, just to ensure you get the right thing out

9:03 lvh: What's the idiomatic data structure in Clojure for bytestrings?

9:03 I've been using bytes[] but that just feels super gross.

9:04 clgv: hyPiRion: yeah, looks like a code smell. should be something like (let [r (rand)] (repeat 5 {:a 0 :b r})) to make the intention clear

9:05 SagiCZ1: hyPiRion: nope that is a mistake

9:05 hyPiRion: why is not calling random again?

9:05 justin_smith: lvh: you can use a vector of Byte values, byt bytes[] is an actual array of bytes, and is the right way to represent that

9:06 lvh: justin_smith: also mutable though right

9:06 justin_smith: right

9:06 what do you mean by "bytestring", actually?

9:07 arrays of bytes are not CharSequences because they are made of 8 bit signed values

9:07 llasram: SagiCZ1: Because you are calling it yourself vs passing the function `rand` to something

9:07 ,(repeatedly 5 rand)

9:07 clojurebot: (0.013326642964774371 0.40762242985735264 0.7708784528135172 0.9785686587084479 0.7638473865027904)

9:07 justin_smith: lvh: maybe you want an array of shorts, or even ints, if you want to represent anything beyond 8 bits

9:08 SagiCZ1: ,(repeatedly 2 (fn [] {:a (rand) :b (rand)}))

9:08 clojurebot: ({:a 0.7095231468043378, :b 0.2359827909847596} {:a 0.7883582125143982, :b 0.8835072257869794})

9:08 SagiCZ1: this is what i want

9:08 i just dont like the fn notation

9:08 clgv: SagiCZ1: so why dont you use it? that why? :P

9:08 *way

9:08 SagiCZ1: clgv: fn seems uncool to me

9:08 especially with no arguments

9:09 hyPiRion: SagiCZ1: ##(map #(assoc {:a 0} :b %) (repeatedly 2 rand))

9:09 lazybot: ⇒ ({:b 0.7055591223129442, :a 0} {:b 0.004841332288907818, :a 0})

9:09 llasram: SagiCZ1: No no -- `fn` is the coolest

9:09 justin_smith: ,(repeatedly #(hash-map :a (rand) :b (rand)))

9:09 clojurebot: ({:b 0.7774605426166392, :a 0.5457287633034817} {:b 0.9351205665136824, :a 0.10940327234871117} {:b 0.2785826781824663, :a 0.06663172148153373} {:b 0.6237813005636965, :a 0.6235348439569292} {:b 0.2189573584793213, :a 0.11105258859414224} ...)

9:10 justin_smith: yes, fn is awesome

9:10 SagiCZ1: thanks for the ideas

9:10 llasram: ,(repeatedly 2 #(-> {:a (rand)}))

9:10 clojurebot: ({:a 0.3764276763964761} {:a 0.28425055137631283})

9:10 clgv: SagiCZ1: doh!

9:10 lvh: justin_smith: I mean bytestrings as in sequences of bytes. Like a C string, or a Python string.

9:10 justin_smith: Not like a java String, of course.

9:10 llasram: lvh: s/Python string/Python 2 string/

9:10 justin_smith: lvh: yeah, byte-array is that (and is of course mutible)

9:11 lvh: llasram: python3 doesn't exist ;)

9:11 llasram: :-p

9:13 SagiCZ1: another question.. if i want to have an inner function close over some local symbol, can i define it somewhere outside?

9:13 scratch that..

9:14 justin_smith: you can pass local values to a function that creates a new function closing over those values

9:14 SagiCZ1: yep.. gonna do just that

9:14 justin_smith: like the classic make-adder

9:30 SagiCZ1: can i deref atom by destructuring? (doseq [{a :a b :b} [(atom {:a 0 :b 1}) (atom {:a 2 :b 3})]] (println a b))

9:31 clgv: SagiCZ1: no not like that. first deref it to get the value then apply destructuring on the value

9:32 SagiCZ1: ok

9:32 justin_smith: ,(let [{a :a} (atom {:a 42})] a)

9:32 clojurebot: nil

9:32 justin_smith: ,(let [{a :a} @(atom {:a 42})] a)

9:32 clojurebot: 42

9:32 SagiCZ1: yeah that works for let, but not for doseq when u have a coll of atoms

9:32 justin_smith: you *can* destructure an atom, it just won't return the value you want

9:33 SagiCZ1: doseq and let use exactly the same destructuring

9:33 vladh_: Hey guys — does anyone know how I can keep a script running via lein-exec? I’m trying to run a simple cron-style thing with at-at and don’t want to script to immediately.

9:33 to die*

9:33 SagiCZ1: justin_smith: no they dont?

9:34 justin_smith: SagiCZ1: doseq needs a sequence, but doseq and let both call clojure.core/destructure to do destructuring

9:34 SagiCZ1: doseq does that for each element of the sequence separately though

9:35 justin_smith: sure - so it destructures each element of the sequence

9:35 I am just saying the actual destructuring, when it happens, is done by the same function

9:35 SagiCZ1: alright..

9:35 i see

9:36 justin_smith: and my ,(let [{a :a} (atom {:a 42})] a) is exactly analogous to your (doseq [{a :a b :b} [(atom {:a 0 :b 1}) (atom {:a 2 :b 3})]] (println a b))

9:37 but I switched to let because there is less noise there, and the destructuring happens in the same manner

9:37 SagiCZ1: but in let u can solve the problem with prepending @ to the right sight of the binding.. in doseq u cant

9:38 llasram: wat

9:38 justin_smith: (doseq [{a :a b :b} (map deref [...])] ...)

9:38 SagiCZ1: oh.... wow

9:38 mind - blown

9:38 llasram: SagiCZ1: @ is a reader macro for `deref`

9:38 ,`@whatever

9:38 clojurebot: (clojure.core/deref sandbox/whatever)

9:38 SagiCZ1: thats news to me

9:39 clgv: SagiCZ1: well you should probably read the chapter on atoms and refs ^^

9:39 SagiCZ1: clgv: i read it so many times .. i just figured that i should also write some code to help me remember

9:40 my theoretical knowledge of clojure is higher than the practical experience.. im not saying it's very high anyways

9:40 clgv: SagiCZ1: use the chapter while writing code ;)

9:40 SagiCZ1: alright

9:41 lvh: Is x.y.z-SNAPSHOT before, or after x.y.z?

9:41 llasram: lvh: "Before", but snapshots are non-release, so you have no way of knowing what's in one

9:42 justin_smith: llasram: well you can always look inside :P

9:42 but yeah, no way to know beforehand what you'll get if you ask for it

9:42 llasram: justin_smith: Except that the non-pinned SNAPSHOT revision could be updated at any time

9:42 clgv: lvh: use snapshots only for experimenting with new features that are not in any release, since they might sabotage repeatable builds

9:43 lvh: I'm trying to publish software thoguh :)

9:43 justin_smith: llasram: I meant you can check strictly a-posteriori, but really that hardly matters compared to not knowing what you'll get if you ask for it

9:45 clgv: lvh: well at the end of a dev cycle release a non-snapshot, during the dev cycle you can use snapshot versions

9:46 lvh: ok :)

9:48 zeebrah: Y do i need do add the eval here: ((eval (read-string "first")) [1 2 3])

9:48 llasram: zeebrah: mu

9:49 zeebrah: llasram: dont know mmu

9:49 clgv: zeebrah: because you are doing weird stuff ;) a `resolve` would suffice

9:50 ,((resolve (read-string "first")) [1 2 3])

9:50 clojurebot: 1

9:50 zeebrah: clgv: i'm watching bob martin so yes definitely weird :)

9:50 clgv: ,((resolve 'first) [1 2 3])

9:50 clojurebot: 1

9:50 clgv: same ^^

9:50 ,(first [1 2 3])

9:50 clojurebot: 1

9:50 zeebrah: so resolve is taking a symbol and then finding the function? but why is that necessary

9:51 llasram: zeebrah: Needing to manually `read` string which contain code is unusual, and probably means there's a more common way to do whatever you're trying to do

9:51 zeebrah: Or do you just want to understand why a symbol is not identical to the function a particular namespaces maps that symbol to?

9:51 zeebrah: llasram: just trying something out because the dude said you can build lisp code and then execute it using eval

9:51 llasram: i guess :)

9:52 if the symbol is in function position then why doesn't it just work as I expected?

9:52 clgv: zeebrah: what are you watching exactly?

9:52 zeebrah: https://www.youtube.com/watch?v=SYeDxWKftfA

9:52 justin_smith: zeebrah: the normal way is to just type into the repl, it does the eval and read for you

9:52 clgv: zeebrah: since the symbol is a symbol and is not a function

9:52 llasram: zeebrah: So in Clojure (and most Lisps) "reading" and "compiling" are separate steps

9:53 Reading turns text into a data-structure

9:53 Compilation turns a data-structure into code

9:53 zeebrah: clgv: right but its not like there are multiple namespaces so there isnt any ambiguity in just using the only one in the namespace?

9:53 clgv: so Uncle Bob uses Clojure, eh?

9:53 zeebrah: apparently!

9:54 clgv: you explicitly constructed a symbol in your example, so no it can not

9:54 zeebrah: is namespace the right word there? i mean in the sense of lisp 1 and 2

9:54 clgv: if you just put a symbol in call position it is resolved to a function on compilation or an error is thrown

9:54 llasram: zeebrah: In that sense Clojure is a Lisp-1 and has only one "namespace", but it has a concept of namespaces (like CL packages), so the same bare symbol could refer to multiple functions in different namespaces

9:54 zeebrah: oh i see

9:55 justin_smith: symbols can have namespaces, but a bare one doesn't - but it gets resolved according to the mappings of the current namespace to a var

9:55 llasram: ^^ During compilation

9:55 clgv: justin_smith: but not in his case where he explicitely constructed a "symbol value"

9:55 llasram: (well, or manual resolution via e.g. `resolve`)

9:56 justin_smith: ,(map namespace '[foo user/foo sandbox/foo clojure.string/foo])

9:56 clojurebot: (nil "user" "sandbox" "clojure.string")

9:56 justin_smith: clgv: right, not always resolved - but it uses the same rules once you ask for it to be resolved

9:58 zeebrah: so the reason ((read-string "first") [1 2 3]) didnt return 1 is b/c first doesn't yet belong to a namespace but yet it is still a symbol

9:59 justin_smith: it's just the symbol, not the var the symbol points at

9:59 ,((read-string "clojure.core/first") [1 2 3]) ; this is no better

9:59 clojurebot: nil

10:00 justin_smith: resolve says "find the var for this symbol"

10:00 zeebrah: oh

10:00 hyPiRion: ,('+ 1 2)

10:00 clojurebot: 2

10:00 justin_smith: ,((read-string "clojure.core/first") [1 2 3] 1) ;P

10:00 clojurebot: 1

10:01 justin_smith: that's just a trick

10:01 zeebrah: so how is this not like a lisp-2 doing (function ..) first? i thought going to a lisp 1 made that unnecessary

10:01 hmmm interesting

10:01 hyPiRion: zeebrah: Because a symbol is not a function

10:02 justin_smith: zeebrah: in normal code, you type the name of the function, and it gets the value pointed at by the var indicated by the symbol

10:02 zeebrah: understood thanks :)

10:02 justin_smith: ,(let [plus +] (plus 1 1))

10:02 clojurebot: 2

10:02 justin_smith: can't do that in a lisp-2

10:03 hyPiRion: Right. (let ((plus #'+)) (funcall plus 1 1)) is the closest

10:03 justin_smith: which reminds me I should make my above statement more precise: it gets the value pointed at by the local binding, or failing that, var resolution

10:04 zeebrah: does scheme have a version of resolve too?

10:05 SagiCZ1: lets say i refer to a different ns "other-ns" using :require in my (ns) .. i am working in the current ns in repl.. what if i want to change a function in the "other-ns" and reflect the change in my working repl? should i call (ns) again to :require it again? it didnt reflect the changes

10:05 xeqi: does ` have a name?

10:05 justin_smith: xeqi: syntax-quote

10:06 xeqi: quasi-quote, symbol-quote ..

10:06 ah

10:06 thanks

10:06 hyPiRion: I've always referred to it as backquote

10:06 justin_smith: zeebrah: I think in scheme eval is more likely to be used

10:06 hyPiRion: but that's cl history I guess

10:06 justin_smith: here it is called syntax-quote http://clojure.org/reader

10:06 mi6x3m: clojure

10:06 what is a way to extract only a subset of the keys in a map?

10:07 like (subset map [:a :b :c])

10:07 justin_smith: select-keys

10:07 mi6x3m: ,(doc select-keys)

10:07 clojurebot: "([map keyseq]); Returns a map containing only those entries in map whose key is in keys"

10:07 justin_smith: ,(select-keys {:a 0 :b 1} [:a])

10:07 clojurebot: {:a 0}

10:07 SagiCZ1: cfleming: hi, are you here by any chance?

10:08 mi6x3m: (inc justin_smith)

10:08 lazybot: ⇒ 71

10:18 SagiCZ1: ok let me ask once again.. how do i reload a library in repl?

10:19 clgv: SagiCZ1: library or namespace of the current project?

10:19 SagiCZ1: other namespace

10:19 clgv: usually you use "send to repl" or something similar which your ide/editor provides

10:20 SagiCZ1: ok i just tried that and it owrks

10:20 works

10:20 i thought there is some programatic way

10:20 clgv: SagiCZ1: well yeah, there is but you'll end up with tools.namespace then

10:20 SagiCZ1: yeah i dont want that..

10:21 clgv: +likely

10:21 SagiCZ1: but this works so thats fine

10:22 justin_smith: SagiCZ1: (require 'some.ns :reload) works in a vanilla repl

10:22 SagiCZ1: justin_smith: thank you

10:23 justin_smith: clgv: the reason to use tools.namespace there is if a definition is removed from the ns, :reload does not undefine it, right? or is there some other nuance?

10:27 clgv: justin_smith: types and records are problematic. if you redefine a type by reloading its defining namespace other functions from different namespaces that were not reloaded but use that type will break

10:27 justin_smith: ahh, right

10:28 lvh: I have a bunch of forms in a threading macro. I want to conditionally add one. Is there a reasonable trick for that?

10:28 clgv: justin_smith: that's an example from my experience where using require only will break

10:29 elazar: Trying to go through Clojure koans: https://github.com/functional-koans/clojure-koans. Hitting an issue with cons. http://pastebin.com/raw.php?i=mkPrG1zn Any suggestions?

10:29 justin_smith: elazar: note how they create the sequence you are consing onto?

10:30 *they are consing onto

10:30 elazar: Ah, I think I see.

10:30 justin_smith: you have to do the same thing with your sequence

10:30 elazar: Well, I'm a little further now. Thank you, justin_smith. :)

10:30 justin_smith: ,[(:a :b :c :d :e) '(:a :b :c :d :e)]

10:30 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :a>

10:31 justin_smith: :a is a keyword, it invokes get on its args if used in a function position

10:32 elazar: ,(= (quote (:a :b :c :d :e)) (conj (quote (:a :b :c :d)) :e))

10:32 clojurebot: false

10:33 justin_smith: conj is a little funny ##(= (conj [:a :b] :c) (conj '(:a :b) :c))

10:33 lazybot: ⇒ false

10:34 elazar: ,(= (quote (:e :a :b :c :d)) (conj (quote (:a :b :c :d)) :e))

10:34 clojurebot: true

10:34 elazar: ^ Yeah, figured it out. :)

10:34 http://clojuredocs.org/clojure_core/clojure.core/conj <-- second example

10:34 Sorry, first example, second input.

10:35 justin_smith: ,(conj #{:a :b :c :d} :e)

10:35 clojurebot: #{:e :c :b :d :a}

10:48 maxthoursie: lvh: cond-> ?

11:41 sm0ke: using java.jdbc is there a way to preserve order of columns?

11:42 select a,b,c from ... gives {:a 1 :b 2 :c 3} which loses the order

11:42 bja: sm0ke, I can't imagine relying on ordering there is safe

11:44 sm0ke: yes, that is why i am asking, jdbc result is ordered

11:44 bja: https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L800

11:45 it looks like query takes :as-arrays? true to make the result set fn into vdc

11:45 I didn't try it, but it sounds exactly like what you want

11:45 sm0ke: let me try

11:45 thanks bja

11:47 ugh, that is for the outer data structure

11:47 [{},..] instead of '({},..)

11:48 bja: oh

11:48 it looks like the code maps :row-fn across the results

11:49 sm0ke: row-fn is identity by default so internally it is map as lower denominator

11:49 sad

11:50 justin_smith: (map (fn [k] [k (m k)] [:a :b :c])

11:50 )

11:50 where m is the result, and that last arg has the order you want?

11:51 sm0ke: well thats not the point

11:51 justin_smith: what is the point?

11:52 bja: sm0ke, https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L362 exists to turn the raw ResultSet into a seq of maps

11:53 sm0ke: ugh read the comment

11:53 sad

11:54 luqi: Hello everyone. As a beginner in Clojure, I find it really daunting when things go wrong and the stack trace is just huge. Any suggestions on it?

11:54 sm0ke: hmm there is a interesting comment which says "but using into {} should preserve order for up to 16 columns"

11:56 clgv: sm0ke: do you need additional features of the default clojure.java.jdbc functions? if not just write a function that handles the resultset directly

11:56 bja: sm0ke, maybe you only need 16 columns? :(

11:56 justin_smith: luqi: there are various tools for colorizing output to help you find the relevant parts

11:56 sm0ke: no i need more

11:57 grr.. i will have to go back to basic jdbc

11:57 justin_smith: luqi: at this point, I have learned how to read the stacktraces, and I look for the frames that are in files I wrote.

11:58 luqi: yeah, I always look for my files. but they are kinda buried inside massive Java/JVM frames

11:59 justin_smith: luqi: https://github.com/AvisoNovate/pretty

12:00 luqi: this ns in particular https://github.com/AvisoNovate/pretty/blob/master/src/io/aviso/exception.clj

12:00 sm0ke: (inc bja)

12:00 lazybot: ⇒ 1

12:00 sm0ke: (inc bja)

12:00 lazybot: ⇒ 2

12:00 justin_smith: in particular, write-exception

12:00 sm0ke: seems like i was missing the "?" in :as-arrays?

12:00 luxbock: luqi: if you are using Emacs, I find the cider-stacktrace mode you get with C-c C-s pretty helpful

12:01 sm0ke: :as-arrays? indeed is the solution!

12:01 clojer: Anyone know what this compilation error refers to: "NullPointerException clojure.lang.Numbers.ops (Numbers.java:961)" ?

12:01 justin_smith: clojer: you tried to do math on nil

12:01 ,(+ nil 1)

12:01 clojurebot: #<NullPointerException java.lang.NullPointerException>

12:01 bja: nice

12:01 luqi: justin_smith, yeah this looks much nicer!

12:02 clojer: justin_smith: Great, but why doesn't the error come with a line number?

12:02 luqi: luxbock: I am using Vim primarily but I'd love to learn Emacs :)

12:02 justin_smith: luqi: awesome, our own hlship (not online right now) worked on it, and introduced me to it

12:02 luxbock: I use Emacs with evil, which is pretty close to Vim

12:03 justin_smith: clojer: Numbers.java - on another stack frame you may find a line number in your own code

12:03 luqi: Aha, that's actually what I'm thinking about

12:03 clojer: justin_smith: How do I get that in Emacs/cider?

12:03 zwer: join #java

12:03 justin_smith: luxbock: luqi: as far as I am concerned, getting cider to work would be a terrible way to learn emacs

12:04 clojer: (pst)

12:04 clgv: ~guards

12:04 clojurebot: SEIZE HIM!

12:04 clgv: joining #java tsk tsk tsk

12:05 justin_smith: luxbock: luqi: I subscribe to that repo's issues feed, I intend to switch to cider when the bug reports slow down (if they ever do)

12:05 (cider's that is)

12:05 clojer: justin_smith: Brilliant. You're a life-saver.

12:05 justin_smith: clojer: np - I think the decision to only show one line of the exception by default is kind of silly

12:06 clojer: also you can access the last uncaught exception object thrown using *e

12:06 clojer: (pst)

12:06 luxbock: I think the cider-stracktrace mode as a more convenient version of pst

12:07 justin_smith: if you want to assign the exception to some var to do something with later, or write your own code that analyzes the exception, *e is quite handy

12:07 clojer: justin_smith: Damn. I posted this on the clojure mailing list not realising that was a truncated error message :(

12:08 justin_smith: I'm sure this isn't the first or last cider bug / cider UI deficiency that has ended up there

12:09 clojer: justin_smith: Yes and I'm stuck with cider 0.6 as I'm using Emacs Live awaiting the 0.7-compatible update :(

12:09 nbeloglazov: In order to send pull requrest/patches to libs under clojure namespace (e.g. tools.reader) do I have to sign contributor agreement?

12:09 justin_smith: ~emacslive

12:09 clojurebot: No entiendo

12:10 clojer: justin_smith: My Emacs foo is pretty non-existent :(

12:10 luxbock: is there something about Emacs Live that preventes you from getting the latest cider-version from elpa/melpa?

12:10 justin_smith: clojer: emacs live is easy to port to regular emacs, and you can even switch between the two by specifying the config files to run on launch. See also technomancy's https://github.com/technomancy/better-defaults

12:11 clojer: justin_smith: I often wondered if that could be done but never found the details.

12:11 justin_smith: luxbock: not really - but the point of emacs live is you don't want to mess with your own configs freeform yet - you want a compatible zero-effort it just works setup out of the box

12:11 clojer: it's doable, just not compatible with the whole "it just works" thing :)

12:11 clojer: justin_smith: Problem I had in the past was `git submodule <something or other>` wiping out my customisations

12:12 luxbock: hmm right, I think I started out with one of the starter kits and then ditched most of it once I got a handle of how things worked

12:12 justin_smith: clojer: put your .emacs.d under git version control :)

12:12 clojer: justin_smith: Yes, I like what "just works" with Emacs Live

12:12 justin_smith: luxbock: clojer: see the readme from technomancy 's better defaults repo I linked above, has a really good sumarry of the situation

12:13 clojer: justin_smith: Unfortunatley Dr. Sam Aaron is a bit tied up right now to finish testing Cider 0.7 compatibility

12:14 justin_smith: There's an update in the dev packs somewhere but I'd rather not mess about

12:14 justin_smith: fair enough, you could be patient, save yourself some pain, and wait for him to do it, or go through the pain and make it work yourself (or maybe "just barely work, good enough for now")

12:15 clojer: justin_smith: I'll defer to his greater Emacs skills. Emacs Live is great for my laziness, hubris & impatience :)

12:16 justin_smith: clojer: in terms of switching configs, the default config is ~/.emacs.d/init.el (or ~/.emacs for legacy, but that is not recommended) - you can launch emacs -q -l alternate-init.el to use a different init file

12:16 clojer: justin_smith: OK, sounds like it's worth a try.

12:16 justin_smith: this is useful while experimenting, you can copy init.el and then use -q -l to launch an emacs using the alternate, modified init

12:16 without breaking your default init file

12:17 riffraff: mh how does one get a vector of ints with a skewed distribution with test.check? I tried (gen/vector (gen/frequency [[ 50 gen/int 5] [50 gen/int 100]])) but it doesn't seem to work

12:17 martinklepsch: whats (go *(while true)* ... ) good for?

12:18 reiddraper: riffraff: you just need [50 gen/int 5] [50 gen/int 100] isn't a valid syntax for gen/frequency. What are you trying to achieve with that/

12:18 justin_smith: martinklepsch: I assume that's (go (while true (do-async-things)))

12:18 martinklepsch: In clojure it seems to be the default in clojurescript it kills my browser

12:19 reiddraper: riffraff: err, ignore the 'you just need' part of that message

12:19 justin_smith: martinklepsch: related to the fact that js has no threads maybe?

12:20 riffraff: reiddraper, I was trying to say "get a frequency of 50% ints in 0..5 and 50% in 0..100"

12:20 reiddraper: riffraff: use gen/choose to create ranges

12:21 riffraff: isnot gen/choose 0 y the same as gen/int y ?

12:21 reiddraper: riffraff: (def f (gen/frequency [[50 (gen/choose 0 5)] [50 (gen/choose 0 100)]]))

12:22 dnolen_: martinklepsch: it not the default in Clojure either - that will result in burning CPU cycles doing nothing

12:22 riffraff: mh, apparently not

12:22 thanks!

12:22 reiddraper: riffraff: no. And if it were, you'd need parenthesis around (gen/int x)

12:22 martinklepsch: dnolen_: you're right, I had those examples wrong in my memories.

12:24 riffraff: I see, I must have tried [5 (gen/int x)], got an error, tried [5 gen/int x], saw it not exploding and moved on

12:25 martinklepsch: so in (go (while true (do-something (<! c)))) —VS— (go (do-something (<! c))) is the (while true ... useful in what scenario?

12:49 dnolen_: martinklepsch: there aren't really cases where (while true ...) is desirable beyond demo examples, you almost always want loop/recur with some exit condition

12:49 * devn travels back to a simpler time

12:49 devn: using slime + lein-swank again

12:55 justin_smith: devn: how is it?

12:55 devn: simpler

12:57 justin_smith: is that an endorsement? it sounds like an endorsement

13:24 riffraff: Okasu, one last thing I don't really understand about test.check and the above mentioned test. I'd expect to run (tc/quick-check 10 my-prop) and have it test ten random sequencies in a few seconds

13:24 (sorry okasu, I meant "ok", darn autocomplete)

13:25 what appears to happen is that the repl runs forever visiting tens of thousands of nodes

13:34 reiddraper: riffraff: does your test fail?

13:35 if so, then what you are seeing is something called shrinking. depending on your generators and property, the shrinking process may have to do a large search

13:36 clgv: reiddraper: is there a possibility to limit the shrinking search or turn it off completely. On occasions this makes sense.

13:38 reiddraper: clgv: you can wrap your generator (or even your whole property) in gen/no-shrink

13:38 there isn't a way (yet) to pause/cancel/limit shrinking otherwise

13:41 grincher: change the value of the string if the value contains a specific substring? Eg. map = {:a "nora", :b "sara}; if VALUE contains "nora" replace with "bob", if VALUE contains "ra" replace with "ma" etc

13:42 Sorry, how can I iterate a nested map and change the value of the string if the value contains a specific substring? Eg. map = {:a "nora", :b "sara}; if VALUE contains "nora" replace with "bob", if VALUE contains "ra" replace with "ma" etc

13:42 clgv: reiddraper: ok thx

13:42 riffraff: reiddraper, I think that may be it cause if I try to trace the checking of my property I can see it executed a ton of times, but is there a way to ask the quick-check method to fail fast?

13:43 reiddraper: riffraff: wrap the property in gen/no-shrink to disable shrinking

13:43 riffraff: ah perfect thanks

13:43 reiddraper: (tc/quick-check 10 (gen/no-shrink my-prop))

13:44 riffraff: I didn't notice this in the docs, seems what I need thank you very much

13:45 reiddraper: riffraff: not documented at the moment

13:46 justin_smith: ,(reduce-kv (fn [m k v] (assoc m k (-> v (clojure.string/replace #"^nora$" "bob") (clojure.string/replace #"ra" "ma")))) {} {:a "nora" :b "sara"}) ; grincher

13:46 clojurebot: {:a "bob", :b "sama"}

13:47 grincher: thank you justin_smith :)

13:48 justin_smith: of course in real code you would require clojure.string :as string and string/replace

13:48 or something like that

13:49 also if you don't want the substitutions to stack, you would want a cond rather than ->

13:53 grincher: justin_smith, I am getting some "clojure.lang.LazySeq@d055e162" istead of the "bob" value

13:53 justin_smith: with what code? care to share on refheap or a gist?

13:59 gfredericks: ,(clojure.string/replace (str (range 10)) #"clojure\.lang\.LazySeq@[0-9a-f]{8}" "bob")

13:59 clojurebot: "bob"

13:59 justin_smith: lol

14:00 grincher: if you did a lazy op on a string, then you can get a string out the other end with (apply str ...)

14:00 grincher: in my example there are no lazy ops, which is why I asked to see a paste

14:11 grincher: justin_smith, https://gist.github.com/gildo/d8f3c6f7614df2368479

14:15 justin_smith: OK - I don't see anything there where the "bzip2" value would become a lazy-seq

14:15 what yaml lib are you using? I will see if I can reproduce.

14:17 grincher: justin_smith, in line 3 you can find the the parsed yaml

14:17 line 3 == x

14:17 justin_smith: can you share the pr-str version?

14:17 that verison is not readable

14:18 ie. the result of (pr x) or (println (pr-str x))

14:19 grincher: justin_smith, gist updated

14:19 I'am using [circleci/clj-yaml "0.5.2"]

14:22 martinklepsch: I'm trying to write a transducer that takes a map and runs a few api calls based on the maps input, kind of pipelining the output of the first transducer function to the second and so on.

14:23 justin_smith: grincher: https://www.refheap.com/89666 I get bob as expected (see the last line)

14:24 I do see some lazy-seq output there though! I see what you mean.

14:24 martinklepsch: now I have a function that looks kind of like the following https://gist.github.com/mklappstuhl/67a7cde18575ecf4e39d — point is it takes a callback function to return it's result. how do I properly feed that back into the flow of the transducing function?

14:25 do I put it in a channel and take from that channel at the end of that function?

14:26 am I maybe on the wrong path using transducers here?

14:27 Bronsa: ,(clojure.string/replace (range 10) #"" "")

14:27 clojurebot: "clojure.lang.LazySeq@9ebadac6"

14:27 Bronsa: justin_smith: ^

14:27 justin_smith: grincher: https://www.refheap.com/89666 updated, no longer tries to regex replace non-strings

14:27 Bronsa: yeah, I just caught that :)

14:28 I guess I can take the apply str out to, for that matter

14:31 grincher: of course you may want to go deeper and recursively work on some of the values that are not strings, updating the strings inside, but what's there should be a start

14:33 grincher: thank you justin_smith

14:35 justin_smith: np

14:40 ,(update-in {:a {:b "value"}} [:a :b] str " modified") ; grincher

14:40 clojurebot: {:a {:b "value modified"}}

14:46 joobus: can someone give me an example of how to use with-open? I was using slurp to fetch a webpage in the repl, but then if i fetched the same page again the output was all garbled. I think it had something to do with not closing the file descriptor.

14:47 justin_smith: joobus: slurp closes the file descriptor

14:47 joobus: hmmm

14:47 justin_smith: joobus: and generally, things like streams get closed properly if they go out of scope in the jvm.

14:48 and given that the stream slurp opens never enters your scope...

14:48 joobus: i guess it was the page i was slurping then

14:48 tenchi: ?reduce

14:49 justin_smith: ~reduce

14:49 clojurebot: reduce accumulates the men from the boys

14:49 justin_smith: haha

14:49 tenchi: justin_smith: Haha...no just a chat issue (not clojure).

14:49 justin_smith: oh, OK

14:50 llasram: joobus: Are you passing `slurp` the URL for a page, or something you opened yourself via e.g. `clojure.java.io/reader` ?

14:50 joobus: (slurp "http://zerohedge.com")

14:50 justin_smith: llasram: oh, good point, I don't even think about that usage

14:50 llasram: justin_smith: But you were apparently correct anyway :-)

14:50 joobus: sometimes it comes back with messed up output, like the charset was wrong or something

14:51 ben_vulpes: I'm using peridot to test some forms with file uploads - does anyone know how to use the peridot (request "/upload" :request-method :post :params {:some "values" :file (file "resources/myfile.txt")) in such a way that it posts all the values in addition to the multipart file? or am i missing something important in how multipart uploads works?

14:51 justin_smith: joobus: sounds like a problem on their end to me, maybe they are load balancing and some of their servers are sending bad content encoding headers

14:51 ben_vulpes: hm i guess if i use a map keyword other than "file" all the headers come through

14:52 joobus: yeah, that sounds reasonably accurate

14:52 justin_smith: joobus: you could try putting the string into a byte-array, then coercing it back to string with various encoding arguments

14:53 joobus: tbh, i don't particularly care about that site, i was just testing out slurp

14:53 justin_smith: &(-> "snowman ☃" .getBytes (String. "UTF-8"))

14:53 lazybot: ⇒ "snowman ☃"

14:53 justin_smith: &(-> "snowman ☃" .getBytes (String. "UTF-16"))

14:53 lazybot: ⇒ "獮潷浡渠�"

15:06 ricky____: I'm going through the unless macro example from Clojure in Action and wondering why when unless is a function, the 'then' portion of the 'if' doesn't get evaluated twice when it's true.

15:07 If it's easier to understand this as code, why does (exhibits-oddity? 7) not show 'Very odd, indeed!' twice? @ http://pastebin.com/JfbjW4QT

15:07 justin_smith: ricky____: then is fully evaluated before the function even sees it

15:08 unless only sees the fully evaluated form - the printing happens before unless even runs

15:08 ricky____: So what does unless actually see as its second argument?

15:09 justin_smith: the return value of the form provided as a second arg

15:09 ricky____: So since it's println, it gets nil?

15:09 justin_smith: in exhibits-oddity? the value is nil

15:09 yes

15:11 ,(letfn [(unless [test then] (println "in unless") (if (not test) (do then (println "unless done"))))] (unless (even? 1) (println "arg to unless")))

15:11 clojurebot: arg to unless\nin unless\nunless done\n

15:11 justin_smith: that should make it clear

15:15 bcm: does anyone here use emacs with add-on packages?

15:15 www.elgethub.com

15:17 thesaskwatch: Hi .. is there some simpler / idiomatic mechanism for pub-sub pattern than atom and adding watches to it?

15:18 justin_smith: thesaskwatch: you can do pub-sub nicely with core.async

15:18 http://yobriefca.se/blog/2014/06/04/publish-and-subscribe-with-core-dot-asyncs-pub-and-sub/

15:19 thesaskwatch: justin_smith: ok, but my use case uses blocking i/o

15:22 justin_smith: thesaskwatch: what about blocking from outside the go block, and sending to a channel when the io completes?

15:22 or doing a blocking read from outside a go block, before a blocking write outside a go block, for that matter

15:23 thesaskwatch: justin_smith: I'm not sure how all those mechanisms are gonna work together. I'm wring an irc client. I'd like to be able to start it and send/receive messages asyncronously (which is a hint for core.async, true).

15:24 justin_smith: thesaskwatch: all that said, there is pubsub via 0mq http://zguide.zeromq.org/clj:psenvsub

15:24 thesaskwatch: justin_smith: so I guess I could start a thread within this client and return two channels

15:24 wring -> writing

15:25 justin_smith: so, if you want to send / receive messages, what about having a go block doing pub sub with an input channel and output channel, then writing to the input and reading the output from your other threads?

15:25 schmee: thesaskwatch: I'm doing a client server thing as well, I have a thread that just reads things of the socket and push them onto a channel

15:25 justin_smith: all the IO can be on the outside of the go block

15:25 schmee: then all the other communication happens over channels

15:26 justin_smith: schmee: yeah, what thesaskwatch needs sounds like that plus a third thread that writes out to the TCP connection again

15:27 thesaskwatch: I actually don't mind using a real thread, there will be no many connections

15:27 milos_cohagen: thesaskwatch: i wrote a wrapper for netty and core async https://github.com/marsmining/nettyca it's an example for simple tcp server

15:27 thesaskwatch: milos_cohagen: thanks, I'll take a look

15:27 schmee: justin_smith: yep, that's how I'm doing it now

15:28 milos_cohagen: thesaskwatch: maybe you could write the client code :)

15:28 schmee: thesaskwatch: it seems to work pretty well, although I have no experience whatsoever in writing servers

15:28 thesaskwatch: milos_cohagen: yeah, I have to wrap my head around it first :)

15:29 schmee: could you share the code with me?

15:30 schmee: or is it proprietary?

15:33 phuu: hey #clojure. core.async question. why does alts! get priority if I <! then alts! in separate go blocks? gist here https://gist.github.com/phuu/32ab6737141d989ea280

15:34 given (def c (chan)) and (def c2 (chan))

15:34 dnolen_: phuu: it doesn't get priority, you should assume the behavior is non-deterministic

15:37 phuu: dnolen_: ah, ok. i must have just got the same result a few times in a row.

15:38 dnolen_: is this true of multiple takes? if i <! 3 times then >!, is the choice also non-deterministic?

15:39 dnolen_: phuu: yes

15:39 phuu: Ahha!

15:39 right. well, i got my JS channel implementation wrong then

15:39 milos_cohagen: phuu: assuming the takes are each in their wn go block

15:40 *own

15:40 phuu: milos_cohagen: right

15:45 ok, thanks both

16:29 SagiCZ1: any easy way to destructure map within map?

16:30 (let [<desctructuring> {:a {:x 0 :y 2} :b 3}] ... get 0 and 2 ..

16:31 llasram: SagiCZ1: yeah -- destructuring nests

16:31 xeqi: ,(let [{:a {:keys [x y]}} {:a {:x 0 :y 2} :b 3}] [x y])

16:31 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

16:32 llasram: ,(let [{{:keys [x y]} :a} {:a {:x 0 :y 2} :b 3}] [x y])

16:32 clojurebot: [0 2]

16:32 xeqi: bah

16:32 Bronsa: heh

16:32 llasram: zoom

16:33 SagiCZ1: ok.. i thought it was possible.. thank you guys

16:33 Bronsa: TBH I Never use "multiple levels" destructuring, it gets kinda noisy IMHO

16:34 xeqi: agreed, I usually just make another binding in the let

16:40 SagiCZ1: why does this not work?

16:40 ,(apply String. "hello" ["world" "!"])

16:40 clojurebot: #<CompilerException java.lang.ClassNotFoundException: String., compiling:(NO_SOURCE_PATH:0:0)>

16:40 SagiCZ1: cant apply on constructors?

16:40 could the exception get any more stupid?

16:41 xeqi: "error"

16:42 SagiCZ1: yeah.. but seriously class not found? how did it even get to THAT

16:42 hyPiRion: SagiCZ1: String. is not a class

16:43 (String. ..) is syntactic sugar for (new String ..)

16:44 ,(macroexpand '(String. "foo"))

16:44 clojurebot: (new String "foo")

16:44 hyPiRion: ,(macroexpand '(apply String. "foo" ["bar" "baz"]))

16:44 clojurebot: (apply String. "foo" ["bar" "baz"])

16:44 SagiCZ1: ,(apply (partial new String) "hello" ["world" "!"])

16:44 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: new in this context, compiling:(NO_SOURCE_PATH:0:0)>

16:45 hyPiRion: and new is a macro, heh.

16:45 SagiCZ1: >:C

16:45 llasram: SagiCZ1: Unfortunately you can only `apply` functions, and there's nothing built into Clojure for turning constructors into functions

16:45 SagiCZ1: ,(macroexpand '(new String "foo))

16:45 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

16:45 SagiCZ1: ,(macroexpand '(new String "foo)))

16:45 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

16:46 hyPiRion: forgot a "

16:46 SagiCZ1: ,(macroexpand '(new String "foo"))

16:46 clojurebot: (new String "foo")

16:46 SagiCZ1: wat

16:46 is it a special macro then?

16:46 hyPiRion: yes. it's a core macro.

16:47 It's probably better to call it a special form (?)

16:47 SagiCZ1: mmkay.. no apply for me then..

16:47 well i could wrap the constructor in a function if i wanted

16:54 ben_vulpes: has anyone ever seen wrap-multipart-params fail to do the expected tempfile behavior?

16:57 blaenk: I'm wondering if I create an uberjar out of my program, how can I handle (can I?) external configuration files? so preferably I'd like for a configuration file to be along-side the jar file, not within it, so that it can easily be edited

16:59 ben_vulpes: blaenk: i uberjar my apps and launch them in docker containers with environment variables

16:59 blaenk: cool

16:59 ben_vulpes: course, that entails all sorts of other overhead in deploy...

17:00 xeqi: ben_vulpes: expected tempfile behavior? I've had problems when I attempted to read it twice

17:02 ben_vulpes: xeqi: i'm failing to even get wrap-multipart-params to write the file to disk instead of reading it in as a...string?

17:03 mi6x3m: if x is a function returning a function

17:03 is there a saner way to call the result than ((x)) ?

17:03 ben_vulpes: in the "file" paramter in :multipart-params, i'm just getting a string and in the body of the request I'm getting a buffered input stream.

17:03 mi6x3m: what's insane about ((x))?

17:04 mi6x3m: dunno, looks kinda funny

17:05 ben_vulpes: dem parens

17:05 lodin: mi6x3m, I guess you could do (apply (x) [...]), but I would hesitate to call that saner.

17:05 catern: (trampoline x)

17:05 (please don't)

17:06 jjido: catern: hey, I like trampoline ;)

17:06 catern: jjido: i do too :)

17:06 jjido: catern: for trampoline work though

17:06 catern: but i was just joking, please don't use it for this

17:07 unles you're

17:07 trampolining an algorithm

17:07 in which case, do use it

17:08 lodin: Particularly, don't use it if ((x)) can return a function.

17:10 Is there any function f such that (into (empty x) (f x)) is the same as x, other than #(into (empty %) %)?

17:12 catern: id

17:13 er, identity

17:13 lodin: catern, identity fails for lists.

17:14 catern: `(into (empty '(42)) (identity '(42)))

17:14 er

17:14 ,(into (empty '(42)) (identity '(42)))

17:14 clojurebot: (42)

17:15 lodin: ,(let [f identity x '(1 2 3)] (into (empty x) (f x)))

17:15 clojurebot: (3 2 1)

17:15 catern: oh, right

17:16 gfredericks: lodin: so your #(into (empty %) %) works because it reverses a list twice?

17:16 lodin: gfredericks: right.

17:16 gfredericks: Not a very nice solution.

17:16 gfredericks: lodin: why on earth do you need such a thing?

17:17 lodin: gfredericks: Makes it easier to deal with mixed seqables when the return type is important.

17:18 llasram: lodin: If the return type is important, your function should return an instance of the correct type

17:19 lodin: I can't think of a situation where I've needed a function which took either a list or lazy seq or a vector and was guaranteed to returned an instance of the same type

17:20 bcm: hi clj-learner

17:20 amalloy: llasram: well, conj

17:20 clj-learner: hi

17:20 llasram: amalloy: pfft, fine :-p

17:20 But just `conj`

17:21 gfredericks: also into

17:21 lodin: llasram: Right, and into uses conj.

17:21 gfredericks: and intos uses into and multi-intos uses intos

17:29 hyPiRion: Where's fmap when we need it

17:29 lodin: llasram, Consider (defn map-generic [f x] (into (empty x) (map f (into (empty x) (seq x)))))

17:30 then (= (map-generic inc [1 2 3]) [2 3 4]) and (= (map-generic inc #{1 2 3}) #{2 3 4}) and (= (map-generic #(update-in % [1] inc) {:a 1 :b 2 :c 3}) {:a 2 :b 3 :c 4})

17:31 llasram: lodin: I honestly have difficulty imagining wanting that :-)

17:31 hyPiRion: lodin: huh, I'm not sure the last example is correct

17:32 I think you want (fn [[k v]] [k (inc v)]) instead of that anonymous function

17:33 gfredericks: ,(defn applicate [& fs] (fn [& vals] (mapv #(%1 %2) fs vals)))

17:33 clojurebot: #'sandbox/applicate

17:33 gfredericks: ,((applicate identity inc) [:foo 41])

17:33 clojurebot: [[:foo 41]]

17:33 gfredericks: oh right

17:33 lodin: ,(defn map-generic [f x] (into (empty x) (map f (into (empty x) (seq x)))))

17:33 clojurebot: #'sandbox/map-generic

17:33 hyPiRion: lodin: however, have you looked at fluokitten? it provides an fmap function

17:33 lodin: (= (map-generic #(update-in % [1] inc) {:a 1 :b 2 :c 3}) {:a 2 :b 3 :c 4})

17:34 ,(= (map-generic #(update-in % [1] inc) {:a 1 :b 2 :c 3}) {:a 2 :b 3 :c 4})

17:34 clojurebot: true

17:34 hyPiRion: lodin: ohh

17:35 * hyPiRion hasn't been using update-in on a vector in ages

17:37 zwer: llasram the idea is that the caller picked an approriate sequence type, and that the function that is processing it generically shouldn't change it

17:39 llasram: zwer: Sure, I get the idea. I just disagree that it is (very often) useful

17:44 lodin: llasram: I figured (empty x) and (conj) is for situations when you want to deal more generally with a collection.

17:54 SagiCZ1: hi.. how do i get the first element from seq of maps that has 0 as a value of :number? [{:number 6 :a 0} {:number 0 :a 3}] --->{:number 0 :a 3}

17:55 llasram: SagiCZ1: (first (filter (comp zero? :number) ...))

17:56 luqi: SagiCZ1: also you can use some

17:57 (some (comp zero? :number))

17:57 amalloy: luqi: try that; it won't work

17:58 SagiCZ1: yeah comp will be handy

17:58 gfredericks: clojurebot: amalloy is <reply> try that; it won't work

17:58 clojurebot: 'Sea, mhuise.

17:59 luqi: hmm, I see.

18:00 my bad. some won't work

18:11 martinklepsch: (def xform (comp (map fetch-data) (map munge-data)))

18:11 is that something transformers are meant for?

18:13 I have a fn that I want to map over a seq that has side effects and I'm not sure how to do that or if it's the right thing at all

18:14 justin_smith: martinklepsch: do you want both the side effects and the results?

18:17 martinklepsch: justin_smith: yes. I'm trying to implement some sort of pipeline: channel-in > fetch-data > do something with data > return result of last function in pipeline

18:19 I was initially thinking about using map< for that but now I'm not even sure if that would have been the right approach

18:25 justin_smith: reduce is eager, and you can build up your result either element by element or by accumulating a total, whichever is apropriate

18:28 martinklepsch: justin_smith: so in my case element by element is what I want, right? do you think the scenario I described makes sense for using transducers?

18:29 justin_smith: it really does (from what I have seen - have not used transducers yet myself, but this looks right for them)

18:46 martinklepsch: justin_smith: ok, thats reassuring enough to keep digging :)

18:46 thanks

18:56 justin_smith: pipeline-async looks exactly like what I'm trying to do: https://github.com/clojure/core.async/blob/e7de6747e5d90e08fb9d6d6dbe41c2bdd1ef00a0/src/main/clojure/clojure/core/async.clj#L523

19:57 lavokad: why :keys can only be bind to symbols which the same names as the keys?

19:57 amalloy: lavokad: :keys is shorthand for doing exactly that; if you want to give explicit names, use the longhand map-destructuring form

19:58 ,(let [m {:xpos 1, :ypos 2}, {x :xpos, y :ypos} m] [x y])

19:58 clojurebot: [1 2]

21:00 zanes: Is there a built-in function that takes a seq and returns the same seq with repeating values removed?

21:00 I feel like this exists, but I can’t find it.

21:01 tac_: like a uniq?

21:02 zanes: For example, (non-repeating [1 1 1 2 3 3 1]) ; => (1 2 3 1)

21:02 It’s pretty simple to write.

21:03 amalloy: &(doc distinct)

21:03 lazybot: ⇒ "([coll]); Returns a lazy sequence of the elements of coll with duplicates removed"

21:03 amalloy: oh, but you want to remove only consecutive duplicates

21:04 &(map first (partition-by identity [1 1 1 2 3 3 1]))

21:04 lazybot: ⇒ (1 2 3 1)

21:06 zanes: amalloy: So, I tried that, but I’m in a situation where the second value of the lazy sequence being consumed may take a while.

21:06 I’d love for the first value to be realized immediately, rather than only after a change happens.

21:06 Does that follow?

21:06 amalloy: sure. you have to write that yourself, but it's not hard

21:06 zanes: Okay, great.

21:07 Ifiht: '(def s "lorem ipsum datum")

21:08 '(def s "lorem\u000A ipsum\u000A datum\u000A")

21:08 '(println s)

21:09 oh darn, no clojurebot.

21:10 justin_smith: ,"Hello Ifiht"

21:10 clojurebot: "Hello Ifiht"

21:10 Ifiht: ,8

21:10 clojurebot: 8

21:10 Ifiht: ,"Thanks justin"

21:10 clojurebot: "Thanks justin"

21:11 Ifiht: ,(def s "lorem\u000A ipsum\u000A datum\u000A")

21:11 clojurebot: #'sandbox/s

21:11 Ifiht: ,(println s)

21:11 clojurebot: lorem\n ipsum\n datum\n\n

21:11 Ifiht: ,(def s "lorem ipsum\u000A datum\u000A")

21:11 clojurebot: #'sandbox/s

21:11 Ifiht: ,(def s "lorem\u000A ipsum\u000A datum\u000A")

21:11 clojurebot: #'sandbox/s

21:12 zanes: amalloy: Something like this? https://gist.github.com/zane/33a5b77162441ec3a25e

21:12 Ifiht: ,(def s (split s #"\u000A"))

21:12 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: split in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:12 Ifiht: ,(def s (clojure.string/split s #"\u000A"))

21:12 clojurebot: #'sandbox/s

21:12 Ifiht: ,(def s (sort s))

21:12 clojurebot: #'sandbox/s

21:13 justin_smith: Ifiht: does \u work the same way in regexes?

21:13 Ifiht: It does in my code, let's see

21:13 ,(print s)

21:13 clojurebot: ( datum ipsum lorem)

21:14 justin_smith: it would sort weird because of the the leading spaces though

21:14 Ifiht: yes

21:14 (def s (clojure.string/trim-whitespace s))

21:14 ,(def s (clojure.string/trim-whitespace s))

21:14 clojurebot: #<CompilerException java.lang.RuntimeException: No such var: clojure.string/trim-whitespace, compiling:(NO_SOURCE_PATH:0:0)>

21:15 Ifiht: ,(def s (clojure.string/trim s))

21:15 clojurebot: #<CompilerException java.lang.ClassCastException: clojure.lang.ArraySeq cannot be cast to java.lang.CharSequence, compiling:(NO_SOURCE_FILE:0:0)>

21:15 amalloy: zanes: yes, that's a fine implementation. i would make a few changes: (1) "last" is a pretty confusing name; i'd call it "prev". (2) i would start each arity with (lazy-seq ...) instead of putting it in the middle; (3) you should use when-first instead of when-let/first (especially because your implementation is broken for seqs containing nil or false)

21:15 zanes: Great feedback. Thanks!

21:15 Ifiht: ,(def s "lorem ipsum datum")

21:15 clojurebot: #'sandbox/s

21:16 Ifiht: ,(def s (clojure.string/split s #"\u0020"))

21:16 clojurebot: #'sandbox/s

21:16 Ifiht: ,(print s)

21:16 zanes: Is it always more idiomatic to start each arity with lazy-seq?

21:16 clojurebot: [lorem ipsum datum]

21:16 Ifiht: got it

21:16 amalloy: zanes: there are probably some exceptions, but none spring to mind

21:17 Ifiht: ,(def s (join (str "(latin)" \u000A) s))

21:17 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: join in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:18 justin_smith: Ifiht: you can send messages to clojurebot

21:18 Ifiht: unless there is something you are trying to show all of us

21:18 or even run your own repl locally

21:18 Ifiht: yes, I have it working locally, but clojurebot doesn't have my code, one step left?

21:19 ,(def s (clojure.string/join (str "(latin)" \u000A) s))

21:19 clojurebot: #'sandbox/s

21:19 Ifiht: YES

21:19 ,(println s)

21:19 clojurebot: lorem(latin)\nipsum(latin)\ndatum\n

21:19 Ifiht: THERE!!! ^

21:19 can anyone tell me why join skips the last item?

21:20 justin_smith: it only goes between items

21:21 amalloy: Ifiht: also instead of writing a million separate lines with def, collapse it all into one form with let

21:22 Ifiht: would let still work if I want to use the same identifier?

21:23 justin_smith: you can repeat ids in let

21:23 llasram: ,(let [s 1, s (inc s)] s)

21:23 clojurebot: 2

21:23 justin_smith: ,(let [s "a" s (str s "b") s (str s "c")] s)

21:23 clojurebot: "abc"

21:24 Ifiht: Thanks justin, amalloy. I'll do that.

21:26 bounb: do you clojure-heads have the feeling you could never go back to your C++/Java days

21:27 justin_smith: bounb: horses for courses

21:27 there are certain things I would never do in c++/java, other things I would never do in clojure

21:28 though personally for lower level stuff I would skip straight from c to java and not touch c++ if it was purely up to me

21:28 bounb: hm so it's philosophy does not revolutionize they way you approach programming

21:28 justin_smith: oh it does

21:28 but there are some things clojure will never be good at

21:28 but the set of things c will never be good at is larger

21:30 bounb: "never" meaning "due to some actually existing irreparable theoretical shortcoming"?

21:30 justin_smith: bounb: for example there are certain tasks in clojure where even (especially) an experienced clojure dev will tell you you are better off writing some java code rather than trying to do that task in pure clojure

21:31 bounb: heap allocated persistent data structures are bad for realtime, and are not cache-line friendly

21:31 for example

21:31 bounb: wow ok

21:31 my bubble is slightly deflated

21:32 justin_smith: also, clojure has to be able to redefine certain things at runtim - which is terrible for your heap usage - it won't really fit in embedded

21:32 bounb: aha

21:32 justin_smith: all that said, clojure is awesome - it isn't perfect for all tasks though

21:32 zanes: amalloy: Out of curiosity, how would you do it without multiple arities?

21:32 bounb: so you have to make considerations of hardware to find the negatives?

21:33 that doesn't bother me. storage/computation is bigger and faster day by day

21:33 amalloy: zanes: (defn whatever [xs] ((fn [xs prev] (lazy-seq ...)) (rest xs) (first xs)))

21:33 zanes: Ah, okay.

21:34 justin_smith: bounb: it's more like knowing what your limitations are - if your requirements include low ram usage, fast startup time, low gc churn, or cache friendliness / low latency, than clojure is likely not a good fit. But much of programming does not have these limitations.

21:34 amalloy: and that is actually how i would write it: i generally prefer helper lambdas over multiple arities. but i don't think it's important enough to suggest it as a critique

21:34 zanes: Cool. Thanks!

21:34 bounb: justin_smith: well said. thanks

21:35 justin_smith: np

21:35 bounb: i'm just a smitten newbie

21:35 watched several hours of hickey talks in the past couple days

21:36 justin_smith: cool, he is a good speaker

21:36 bounb: yeah absolutely

21:36 which other speakers in the programming/comp sci world are on his level

21:38 justin_smith: I saw a Rob Pike speak once, he was pretty good

21:38 bounb: i see him almost like a prophet, a visionary the way he speaks (ok sounds a bit sycophantic but honestly)

21:38 yeah! i like rob pike too

21:38 seen a couple great talks from him on go/concurrency

21:40 hickey is basically showing me everything i thought i knew about programming is wrong

21:41 it can be really simple

21:42 zanes: amalloy: That’ll drop the first value, no?

21:42 amalloy: zanes: yes, you need to be more careful than i was; i just wanted to show you the structure of the helper-function skeleton

21:42 * zanes nods.

21:46 zanes: bounb: Maybe Joe Armstrong?

21:46 bounb: thanks!

21:53 justin_smith: related question then. does your job impose those limitations - if not, do you use clojure at work?

21:53 justin_smith: bounb: yup, I do backend for web stuff, and use clojure

21:54 and I love it

21:54 (inc clojure)

21:54 lazybot: ⇒ 19

21:54 bounb: ah that is good to hear

21:54 (inc clojure)

21:54 lazybot: ⇒ 20

21:54 bounb: is this like a karma system

21:54 justin_smith: $karma clojure

21:54 lazybot: clojure has karma 20.

21:54 justin_smith: indeed it is :)

21:55 it looks like clojure code, but really it is just a command for the bot

22:00 bounb: (repeatedly (partial inc bounb))

22:00 am i doing it right?!

22:00 justin_smith: it's just a pseudo-syntax

22:00 also, the partial wouldn't execute

22:01 ,(repeatedly (partial + 1))

22:01 clojurebot: (1 1 1 1 1 ...)

22:01 bounb: disappointed :(

22:01 justin_smith: or wait, yeah it would

22:01 d'oh

22:01 bounb: B)

22:01 (tbh i tested it first)

22:01 (inc bounb)

22:01 lazybot: You can't adjust your own karma.

22:02 bounb: foiled!

22:04 iamdustan: I’m just starting to learn clojure so decided to do some codeeval challenges with it

22:04 but I am always blowing the memory constraints of codeeval

22:04 anyone else experience this?

22:05 justin_smith: if they have ram limits, that's gonna be rough on clojure

22:05 tac_: iamdustan: what are codeeval challenges?

22:05 justin_smith: https://www.codeeval.com/

22:05 iamdustan: e.g. simple sorting. my memory usage is 65413120 bytes

22:05 bounb: the copy on that site is funny

22:06 tac_: iamdustan: are you using recursion?

22:06 bounb: "unlock exclusive hacker deals"

22:06 justin_smith: iamdustan: yeah, clojure needs to load the whole language into memory at runtime (though arrdem tried to change that - but it looks like that will become a different language)

22:06 iamdustan: with this code: https://gist.github.com/iamdustan/83d8f3c8759e31eb0f74

22:07 bounb: haha yeah let’s pretend it doesn’t say that

22:07 tac_: I don’t believe I am

22:07 justin_smith: iamdustan: what's with the redundant vec call on line 7?

22:07 iamdustan: bounb: the design of that site is just as bad as the copy.

22:07 justin_smith: oh nice. I didn’t even realize I had done that when I added the map

22:08 bounb: yeah it's so cheesy

22:08 "Incredible profile pages that allow you to show the info you want while protecting your privacy."

22:08 justin_smith: iamdustan: that will help with ram a little - but the main factor unless your task is huge is going to be the huge resident size of clojure itself

22:08 bounb: WOW what a great feature so generous

22:09 sorry i'm not helping you

22:09 iamdustan: bounb: you are adding to my nightly entertainment :)

22:10 bounb: haha good

22:10 iamdustan: I realized why I have no stackoverflow answers for anything...all the attempted answers I’ve begun to write were troll-ish in nature.

22:10 bounb: i can't wait to redeem an Exclusive Hacker Deal IRL!

22:11 iamdustan: justin_smith: thanks a lot. Good to know that even though clojure is “supported” it’s not possible to pass their requirements.

22:11 bounb: http://cl.ly/image/1c0q0p2n3W0s

22:12 bounb: LOL

22:12 justin_smith: iamdustan: you could suggest they look at the baseline size mem usage wise of "lein repl", and only count usage past that, but it seems like that would require reworking their whole deal

22:12 iamdustan: We recommend everything

22:12 bounb: they so keen to sell yr info to other companies

22:12 "Not recommended"

22:12 iamdustan: oh yeah. the “actually” private one

22:12 bounb: because then we can't monetize you

22:13 iamdustan: justin_smith: good idea. it’d be nice to at least see my own success progress through these.

22:13 dbasch: iamdustan: https://getsatisfaction.com/codeeval/topics/clojure_time_memory_stats_seem_wrong

22:15 iamdustan: dbasch: I just started reading that same thread

22:15 from 2013 so you’d think something would be fixed by now

22:17 and that thread proves justin_smith correct

22:17 justin_smith: also, regarding the comment on that page that "clojure needs the whole jvm" - the jvm is lazily loaded to some degree, the real bottleneck is that it needs the whole of clojure compiled and in memory at runtime

22:18 andrewchambers: dnolen_: I found the thing I was talking about before http://bddbddb.sourceforge.net/ . I don't know if its the sort of thing you are interested, datalog, binary decision diagrams and program anaylsis.

22:18 dnolen_: andrewchambers: I'm aware of it :)

22:18 bounb: pop poll: who here is not a linux user

22:18 justin_smith: iamdustan: and that's the nature of clojure - they are just measuring things in a way that is not friendly to this language

22:18 andrewchambers: cool :)

22:18 catern: bounb: are you a Linux user?

22:18 bounb: no comment

22:19 catern: i see

22:19 you are interested in switching

22:19 well do so

22:19 andrewchambers: I liked the part where they said pointer anaylsis was 10 times less code and ran a bit faster in datalog

22:20 catern: it saves so much effort in the long run

22:20 zanes: Is there a reason why clojure.core functions like distinct don’t have a 0-arity version that returns a transducer?

22:21 justin_smith: catern: as a linux user of 15+ years now, I'll have to say it can also be a huge pain in the ass. But if you don't play flashy games or do graphic design work and you like good command line tools, it's great.

22:21 bounb: catern: nah, i am a fairly long time user. just wanting to confirm my suspicion that this community is pretty much a subset of the community of linux users

22:21 iamdustan: justin_smith: thanks for the help.

22:21 justin_smith: iamdustan: np, too bad about how they are scoring our favorite language

22:22 bounb: justin_smith: well said again about linux

22:22 catern: bounb: oh okay. well in that case, no, there's probably a lot of OS X users around, judging by today's sad trends

22:22 bounb: we don't really have any good OSs

22:22 they're all a bit naff in various ways

22:23 justin_smith: just by observation I would say that OS usage in the clojure community is in order: osx, linux, windows

22:23 bounb: oh i see

22:23 yes i forget just how big apple is these days

22:23 justin_smith: that's really informal :)

22:23 bounb: justin_smith: don't worry. it was a "pop poll"

22:24 im not writing a scientific study

22:24 justin_smith: and I'd say in terms of convenience of developing clojure, the ranking is linux, osx, windows

22:25 but that's even more subjective

22:26 zanes: amalloy: I guess the most succinct implementation is (partial sequence (comp (partition-by identity) (map first))). Heh.

22:27 Or maybe that would have the same problem of delaying the first value. Hm.

22:27 iamdustan: justin_smith: ha. That’s a bit of a stretch for me yet. I still will claim javascript as my fave, but I’m excited about clojurescript and om.

22:28 blaenk: anyone use cljsbuild? I have it in my :hooks and it keeps saying Compiling ClojureScript whenever I run lein repl lol

22:28 thought it was only supposed to run when other things were run, such as compile and clean

22:28 amalloy: zanes: probably does, yeah

22:30 bounb: iamdustan: javascript is your favourite language?

22:31 iamdustan: bounb: guilty

22:31 andrewchambers: iamdustan: what languages have you used?

22:31 iamdustan: bounb: though that is not for breadth of experience

22:31 bounb: ...explain?

22:31 iamdustan: oh goodness

22:31 * iamdustan starts sweating

22:31 iamdustan: personal history.

22:31 andrewchambers: javascript is pretty average overall

22:32 not super bad

22:32 not great

22:32 iamdustan: I’ve been a developer for ~3 years (that I’ll count at least)

22:32 andrewchambers: You code webstuff only though right?

22:32 iamdustan: and that is all as a front end dev

22:32 zanes: Man, writing transducers by hand is weird.

22:32 andrewchambers: I think you just like javascript because you are comfortable iwth it

22:32 iamdustan: and I went to were I work now to learn back end dev

22:33 andrewchambers: I think typescript is decent

22:33 iamdustan: but they realized how good I was at front end and I got pigeon-holed so I just followed the rabbit trail down

22:33 bounb: anyone here not primarily a "programmer" in their day job?

22:33 dbasch: bounb: you’re assuming everyone here has a day job

22:33 andrewchambers: Software engineer might still be a programmer :)

22:33 iamdustan: I’ve done a bit in python, ruby, read a haskell book, started SICP (since I’m self-taught) which got me into lisps, and then because of Om I shifted to clojure

22:34 bounb: bounb: if you don't then your answer is implicitly "no" and you don't need mention it

22:34 iamdustan: I read most of a C++ book last year, but that was still biased towards web development (browser engines)

22:34 bounb: uh fuck i addressed myself

22:34 dbasch: ^

22:34 iamdustan: haha

22:34 bounb: <- moron

22:34 iamdustan: long-winded way to say, yeah I am a web developer through and through

22:35 andrewchambers: yeah, javascript is decent compared to those. Haskell is just way out there, and just reading doesn't give you the proper feel for it.

22:35 you don't really have any typed languages :P

22:36 iamdustan: true, true. To that point: I have played with typescript and C#

22:36 andrewchambers: but thats ok for what you seem to workon

22:36 iamdustan: well, C++ no?

22:36 andrewchambers: i dunno

22:36 C++ is horrible

22:36 But at least with C and C++ you will learn more fundamental computer science stuff

22:36 since its much lower level

22:37 iamdustan: I have a (former) coworker who is big into haskell and I read the “...for great good” book and finished and was like “that was really interesting and I have no idea how I could solve anything with it if my life depended on it”

22:37 I did write a couple lines of C for a project actually :)

22:37 well, modified.

22:37 andrewchambers: yeah, i dunno clojure is pretty high level and cool once you are used to it

22:38 clojurescript is alot better than javascript imo, but thats just an opinion

22:38 Javascript is quite verbose and the callbacks get very nested

22:38 dbasch: andrewchambers: it depends on what you mean by “fundamental cs stuff.” You do get closer to hardware, but that’s not necessarily what cs is about

22:38 andrewchambers: dbasch: yeah, you are right

22:38 bounb: how can you compare clojurescript and javascript?

22:38 andrewchambers: closer to computer stuff

22:39 not algorithms or anything

22:39 but understanding hardware etc

22:39 iamdustan: it’s like java to javascript. They both have common parts in the name!

22:39 bounb: hah

22:39 andrewchambers: I dunno, clojurescript has its own problems

22:39 like way harder for abeginner to get started

22:39 more setup

22:40 they aren't problems with the language, but they are real problems.

22:40 iamdustan: like everything with java :)

22:40 andrewchambers: To code in clojurescript you need to understand all the javascript stuff AND all the clojurescript stuff

22:40 so its not really beginner friendly

22:40 bounb: correct me if i'm wrong but i thought clojurescript was just a clojure->javascript compiler

22:40 andrewchambers: same with clojure<->java

22:40 iamdustan: I installed maven for a quick freelance project the other day and immediately lost all faith in the java world.

22:41 andrewchambers: java is horrible

22:41 i dunno, The only language that has tools I enjoy is Go at the momeny

22:41 little setup, just works

22:41 bounb: why not clojure

22:41 andrewchambers: clojure is freaking hard to get started with

22:41 stuff is outdated

22:42 the lein project.clj stuff took me ages to get started with

22:42 because the templates i was copying were out of date

22:42 bounb: hmmmmmm

22:42 andrewchambers: then my laptop was really slow

22:42 lein version took 6 seconds

22:42 bounb: so complaints about the language ecosystem

22:42 andrewchambers: to print

22:42 but i understand that

22:43 To use clojure, you need to know java and clojure and the tools

22:43 justin_smith: andrewchambers: I got pretty far with clojure before I learned any java

22:43 andrewchambers: though I did have to figure out just enough to read some javadoc

22:44 andrewchambers: Yeah, but if you don't understand java exceptions or you don't understand what a classpath is

22:44 you are screwed

22:44 someone with experience can easily work it out

22:44 but if you are totally new then its harder

22:44 bounb: andrewchambers: good to hear that point of view. thx

22:44 andrewchambers: I mean, 4clojure is decent

22:44 dbasch: andrewchambers: that’s more jvm stuff than java proper

22:44 andrewchambers: since it lets you play with no setup

22:45 justin_smith: (inc dbasch)

22:45 lazybot: ⇒ 9

22:45 blaenk: anyone know how to generate a certain length random string? I found crypto-random which lets me specifies the size in bytes the size then increases when its encoded in base64 or whatever

22:45 justin_smith: yeah, you need to learn the tooling / ecosystem, but not so much the language (until you decide to go deeper)

22:45 blaenk: I mean, short of truncating the string

22:46 andrewchambers: The clojure language itself is pretty easy.

22:46 My one complaint was the using and ns :refer

22:46 so many ways to include stuff

22:46 justin_smith: blaenk: like cryptographically secure random string?

22:46 andrewchambers: not really explained well anywhere

22:46 blaenk: yep

22:46 to use for ring's cookie key

22:46 dbasch: blaenk: what characters do you want to use / exclude?

22:46 blaenk: I'd just like something that's printable, i.e. no unprintable characters

22:46 dbasch: blaenk: use java uuid

22:47 andrewchambers: all that being said, i think clojure is great once you know how to use it

22:47 blaenk: uuids can be 16 characters long? I don't know the implications of truncating something

22:47 brehaut: tautology is tautological

22:48 iamdustan: what are some use cases that you folks are using clojure for?

22:48 avi__: testing java libraries

22:48 iamdustan: My viewpoint is entirely too focused on the web platform in any fashion

22:49 justin_smith: iamdustan: backend for http

22:49 avi__: I use clojure's repl to test out Jars and explore them before I have to write a lot of java code.

22:49 iamdustan: avi__: interesting. so you still write java, but clojure is to get familiar with something?

22:49 bounb: anyone by the name jony hudson itc?

22:50 iamdustan: justin_smith: with ring and compojure and the like?

22:50 avi__: iamdustan: I try to avoid Java, but yes

22:51 andrewchambers: iamdustan: I have played with writing parts of a compiler in clojure with core.logic

22:51 avi__: iamdustan: it allowed me to plumb the guts of DB4o and see the crazy stuff it was doing

22:51 andrewchambers: didnt actually use it for a few reasons

22:52 then I wanted to use clojurescript + core.async + om for a ui for a payment system

22:52 but shelved that project for now

22:52 I like to try and think of projects that clojure will be good for as a hobby :P

22:52 justin_smith: iamdustan: ring and our own custom router, edn record mapping layer, and template renderer (the project is open sourced, called caribou)

22:53 iamdustan: if/when I get to the point of clojurescript + om I will let you know to pick that project back up

22:53 justin_smith: caribou is a bit too heavy weight / frameworky for clojure (it's an adaptation of some ruby stuff built for an agency to smooth a transition)

22:53 andrewchambers: clojure also changed the way i write some code at work in normal java

22:53 more immutability

22:53 more atomic swapping of values

22:55 bounb: avi__: that's interesting.

22:55 thanks

22:56 andrewchambers: more emphasis on pure functions too

22:58 avi__: so much in java needs to be immutable

22:58 thank goodness they made the strings immutable

Logging service provided by n01se.net