#clojure log - Feb 04 2011

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

0:27 datka: why does (first (map (fn [x] (println x) x) [1 2 3])) print all 3 numbers?

0:28 brehaut: datka: presumably chunked sequences

0:28 datka: also, you can simplify that map to (map println [1 2 3])

0:29 datka: I was trying to use filter identity and first to evaluate only the first element that returned non-nil, but it's doing too many

0:30 I wanted something that wouldn't retun nil

0:30 brehaut: datka: chunked sequences realise a small portion of the whole sequence to improve performance

0:30 if you realy only want to print the first item, how about (println (first [1 2 3]))

0:31 datka: that was just an example, the actual function does a whole lot more

0:31 brehaut: ok sure

0:31 i have to go sorry

0:31 datka: and I really don't want to process more than I have to

0:32 brehaut: but search about chunked sequences; i believe chris houser has a dechunkifiing function somewhere?

0:32 datka: I will, thanks

0:32 brehaut: sorry i cant be more help

0:33 dnolen: datka: or if you're building the sequence to be consumed, you can force it to be one at a time.

0:37 datka: currently, the sequence is a vector stored in a ref.

0:38 dnolen: datka: if it's a vector, then it's not actually going to 'process' more than you ask for.

0:38 datka: what I mean if you're not doing sideeffects, does it matter? I suppose the operation you're doing is expensive?

0:39 datka: actually, it looks like it's really the result of mapping over a vector

0:39 There are some side effects (logging) and it's pretty expensive

0:40 think processing the routes for every page in an application on every request

0:43 I got it

0:46 dnolen: ,(letfn [(lazier [l] (lazy-seq (cons (first l) (lazier (next l)))))]

0:46 (first (map (fn [x] (println x) x) (lazier [1 2 3]))))

0:46 clojurebot: EOF while reading

0:46 dnolen: ,(letfn [(lazier [l] (lazy-seq (cons (first l) (lazier (next l)))))] (first (map (fn [x] (println x) x) (lazier [1 2 3]))))

0:46 clojurebot: 1

0:46 1

0:46 dnolen: is one way.

0:47 probably want to use recur there.

0:48 heh getting late, it's lazy-seq don't need recur

0:48 datka: get an error with recur

0:49 perfect. That did exactly what I wanted

0:51 chouser: hm, map doesn't support chunked seqs when given more than one collection

0:52 zakwilson: What's the ETA on 1.3? Do most libs work with it yet?

0:54 chouser: ,(letfn [(lazier [coll] (map (fn [x _] x) coll (range)))] (first (map prn (lazier [1 2 3]))))

0:54 clojurebot: 1

0:55 dnolen: chouser: heh

0:55 chouser: not sure that's any better, though

0:55 in fact, I'm pretty sure mine's worse.

0:59 dnolen: zakwilson: none that I'm aware of but who knows, a lot of documentation needs to be written up.

1:15 sritchie: edw: hey, you don't happen to be a cascalog user, by any chance

1:16 amalloy: chouser: isn't (fn [x & _] x) effectively (comp first list)?

1:17 hiredman: (fn [[x]] x) please

1:18 (and preferably (comp first list))

1:26 amalloy: hiredman: i always feel devious when i do something like (fn [[x]])

1:27 hiredman: deliciously devious

1:27 amalloy: *chuckle* yeah, some of that too

4:34 neotyk: Good morning

4:35 brehaut: morning neotyk

4:44 ejackson: hey gents.

4:46 konr: hello

5:01 neotyk: in last talk by Stuart Halloway on InfoQ Clojure-Java Interop he mentioned some nice reflection/itrospection for Java classes, do you remember what was it?

5:24 no_mind: how can I append values to a vector

5:24 ejackson: conj

5:25 raek: no_mind: (conj [1 2 3] 4) (conj [1 2 3] 4 5) (into [1 2 3] [4 5])

5:25 no_mind: thnxs

5:31 not working... basically I want a function which returns a vector. The items of vector are generated with some logic. Any example of this ?

5:31 ejackson: (into [] (my-logic-generating-a-seq-of-values))

5:33 no_mind: ejackson: what if I have a pre-defined vector to which I have to ad values. lets say (def vt [1 2]) . Now I want to add values to vt

5:33 Chousuke: you can't change vt

5:33 you can only create a new vector

5:33 design your code so that that is not a problem :)

5:34 no_mind: k

5:34 ejackson: yeah, so create a function that takes in vt as an argument, then conj's to it thereby creating a NEW vector which is returned by the function

5:34 Chousuke: if you really need state, you can use atoms or refs or agents

5:35 but *most* of your code should be stateless

5:35 if you have more than a couple refs, something is probably wrong

5:35 ie, don't wrap a vector in ref just so you can mutate it

5:44 no_mind: Chousuke: ejackson I am pulling some stuff from db and have to return it as json. The clj-json/generate-string requires a vector. What si teh best way to solve this

5:47 ejackson: no_mind: this depends on a lot of stuff. I generally use read-json which takes the string that the db returns and returns an appropriate data structure.

5:47 neotyk: no_mind: (into [] (map . .))

5:48 no_mind: this is what I did (into [] (doseq [i (range 0 10)]{:name "test" :id i})

5:48 but not working

5:49 Chousuke: doseq is for side-effects

5:49 no_mind: k

5:49 Chousuke: you want for, it generates a sequence

5:49 ,(for [i (range 5)] (- i))

5:49 clojurebot: (0 -1 -2 -3 -4)

5:49 neotyk: ,(doseq [i (range 0 10)] i)

5:49 clojurebot: nil

5:50 Chousuke: ,(doseq [i (range 5)] (print i))

5:50 clojurebot: 01234

5:50 Chousuke: see, side-effects only

5:51 generally anything with a do-prefix is for side-effects

5:51 Fossi: ,(print "foo")

5:51 clojurebot: foo

5:51 no_mind: ok

5:51 Fossi: ,(print ",(print \"foo\")")

5:51 clojurebot: ,(print "foo")

5:51 Fossi: smart bot

5:51 ejackson: no_mind: so just replace the doseq in your code with for, and it'll work

5:52 no_mind: k let me try

5:52 Fossi: ,(print "/msg clojurebot ,(print \"foo\")")

5:52 clojurebot: /msg clojurebot ,(print "foo")

5:52 ejackson: no_mind: you can also replace "into []" with plain "vec"

5:53 no_mind: k

5:53 Fossi: funky

5:53 ,(print "foo")

5:53 clojurebot: foo

5:54 Fossi: i guess clojurebot has been tested against a huge amount of attackvectors in the last year :D

5:59 raek: &(print ",(print \"foo\")")

5:59 sexpbot: ⟹ ,(print "foo")nil

6:00 raek: ,(print "&(print \"foo\")")

6:00 clojurebot: &(print "foo")

6:00 sexpbot: ⟹ foonil

6:08 zoldar: hello; is there a way to pass arguments from vector while making an instance of a class? Something like (apply new clazz args) - this one does not work because "new" is a special form. Is there some way around?

6:10 raek: zoldar: you can wrap the constructor in a function if you know the number of arguments: (map #(Foo. %) [1 2 3])

6:11 zoldar: raek, won't it create 3 different instances ?

6:11 raek: zoldar: otherwise, you have to use reflection. clojure.lang.Reflector can help you with that.

6:11 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java

6:11 yes, this was just an example of how you can make a constructor "function like"

6:12 zoldar: ok, so it's not possible without ugly hacks

6:12 raek: but I see that was not maybe what you needed

6:12 no

6:12 clgv: zoldar: it's not an ugly hack to have a constructor method ;)

6:12 s/constructor/factory

6:12 sexpbot: <clgv> zoldar: it's not an ugly hack to have a factory method ;)

6:13 zoldar: ok, thanks

6:14 raek: when the compiler sees (Foo. x), it will look up what constructors are avaiable and compile code that uses one of those

6:14 if you want to choose which constructor to use (arity, signature types) at runtime, reflection is the only option

6:15 zoldar: understood

6:16 raek: (Reflector/invokeConstructor clazz (into-array args))

6:16 zoldar: well, on the other hand, (defmacro make-instance [clazz & args] `(new ~clazz ~@args)) should also do the job in the end

6:17 clgv: zoldar: looks like it would ;)

6:17 no_mind: is there a package to read config file in clojure ?

6:17 raek: well, you can't apply a macro, but for making the syntax prettier, yes. it would work.

6:18 zoldar: raek, crap, forgot about it

6:18 anyways that's still some option

6:19 raek: ,(fn [] (Integer. :foo :bar :baz))

6:19 clojurebot: java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Integer

6:20 raek: yeah, the constructor needs to be found at compile-time (when using new/Class.)

6:36 zoldar: so (clojure.lang.Reflector/invokeConstructor Integer (object-array [4])) is the way to go ?

6:43 http://paste.lisp.org/display/119370 works ok; I wonder - is it so uncommon case that it's not in core? or is it something awfully bad to do in a way I'm missing?

6:53 Chousuke: I've never had need for anything like that :/

6:55 zoldar: ok, it must be me then

6:55 Chousuke: it'd probably be a lot faster to just have a cond with different (Class. a b c) calls in each branch

6:56 reflection is rather slow

6:56 also you don't need to name the parameter "clazz". class is just fine :)

6:56 the function is short enough that shadowing the class function does not matter.

6:58 zoldar: just for the record, my use case for that: http://paste.lisp.org/display/119371

6:59 Chousuke, right, I've just seen "clazz" a couple of times when examining some libraries and took it as a some sort of convention

7:00 Chousuke: it's probably some java habit

7:00 where class is a keyword that you can't use as a parameter

7:00 +name

7:02 style nitpick: your (swap! regisrtry #(...)) thing is equivalent to (swap! registry assoc listener message)

7:02 Dranik: hi all!

7:03 I have just managed to create an example of how to automate java patterns implementation using clojure! Yahoooo! :-)

7:03 zoldar: Chousuke, right, must have overlooked this, thanks

7:03 Chousuke: zoldar: also, AFAIK the I prefix is generally not used with protocols.

7:03 but other than that, I guess what you're doing is fine :/

7:04 zoldar: Chousuke: hmm, I guess I'm looking at the wrong code :) I recall seeing it in the joy of clojure

7:04 Chousuke: it doesn't look like you'll be creating very many of those listener instances

7:04 hmm

7:04 in Clojure itself I is used for interfaces.

7:05 and while protocols do generate an interface, it's more of an implementation detail

7:05 zoldar: Chousuke, generally, there will be only one instance of ListenerRegistry, but I can't think of some better way of putting it together

7:06 although, there may be at some point need for more than one registry

7:06 Chousuke: also do protocols even support varargs? :/ it might've been fixed but that wasn't the case last time I checked.

7:06 zoldar: what do you mean by varargs ?

7:06 Chousuke: & args

7:06 sexpbot: java.lang.Exception: Unable to resolve symbol: args in this context

7:06 Chousuke: sexpbot: :P

7:07 zoldar: hmm, I haven't tried it yet

7:08 Chousuke: you might get weird behaviour

7:08 since & will actually get a parameter bound to it

7:08 zoldar: I'll fall back to a seq then

7:08 Chousuke: so your register method takes six parameters, including this :)

7:08 zoldar: not too neat but still..

7:09 5

7:09 Chousuke: no, I mean the way you've written it

7:09 _, owner, message, listener-class, &, and args :P

7:09 zoldar: aah

7:09 nasty

7:10 Chousuke: the macro could probably warn about that :/

7:10 zoldar: compiler could've warned about it

7:10 Chousuke: it seems to be a common mistake.

7:12 zoldar: I wonder - how clojure-in-clojure will cope with this whole interop mess? Will it be completely platform agnostic?

7:14 Dranik: zoldar, do you mean that somebody is developing clojure in clojure?

7:15 zoldar: Dranik, umm don't current efforts go into that direction? beyond 1.3?

7:15 *in

7:15 Dranik: zoldar, actually I don't know much about 1.3 that's why I'm so curious

7:16 zoldar: well I'm not knowledgeable enough to give any details about this, that's just what I've heard/seen - maybe I was hallucinating ;)

7:17 Dranik: zoldar, :-)

7:17 zoldar: random search result: http://blog.n01se.net/?p=41

7:18 Dranik: zoldar, OK, we have to wait for rhikie and ask him. Guess, he knows...

7:20 zoldar: there's even a bullet point under "Long-term" on http://clojure.org/todo

7:20 Dranik: btw, how is ClojureCLR? Is it still alive?

7:20 zoldar: Dranik: I can confirm that it is :)

7:20 Dranik: :-)

7:20 zoldar: had opportunity to get in touch with dmiller

7:21 there was a bug in compilation procedure - he was very responsive

7:21 even though the problem was messy, 3 days later the fix was there

7:21 Dranik: great!

7:22 may be one day I'll code Clojure in .NET!

7:23 zoldar, seems like the day when Clojure will be as powerfull as CL is near...

7:23 no_mind: how do I find value of a key form a hash-map

7:23 Dranik: pity, no reader macros in long terms...

7:24 zoldar: Dranik, well, I'm not the one to judge about that ;)

7:24 Dranik - I thought that clojure actually has these already

7:24 Dranik: zoldar, its macrosystem lacks some points which CL has

7:24 zoldar: I confess, that I didn't try using these

7:25 I talking about reader macros

7:25 *I'm

7:27 ok, I was wrong, it's achieveable by some sort of hackery: http://briancarper.net/blog/449/

7:29 Dranik: zoldar, wow, that's great!!

7:31 zoldar: ,({:a 1 :b 2} :a)

7:31 clojurebot: 1

7:31 zoldar: <== no_mind

7:32 or maybe I misunderstood

7:33 no_mind: zoldar: thanks, I figured that out :)

7:38 ejackson: oh man, when it works, coding is such a rush !

7:40 zoldar: ejackson, unfortunately for me it doesn't work more often than does, but that may be just sucky me

7:40 ejackson: oh me either, but its those rare and precious times that make it worthwhile

9:02 arnorhs: Is clojure usable without contrib?

9:02 jweiss_: sure

9:02 Dranik: yep

9:03 arnorhs: but isn't there a whole lot of stuff that relies on it?

9:03 jweiss_: any emacs user here able to tell me if I can get method signature in the repl for java method calls (in this case a constructor)

9:03 by repl i mean swank

9:03 slime, whatever

9:03 Dranik: arnorhs, so what's the problem? just add it to the classpath

9:03 arnorhs: no problem

9:04 i'm just wondering exactly what it's purpose is

9:04 i've always just installed it without thinking much about it

9:04 Dranik: arnorhs, it is "batteries"

9:04 arnorhs: isn't it a library?

9:04 Vinzent: jweiss_, if clojure, you can use smth like clojure.contrib.repl-utils/show

9:04 Dranik: yep, its a library

9:05 arnorhs: does eg. compojure rely on it?

9:05 jweiss_: Vinzent: i mean a builtin emacs function, to show the signature in the minibuffer space

9:05 Dranik: arnorhs, guess so, bcs contrib has lots of good stuff

9:05 zoldar: is there a way to avoid writing macro in case when the only thing i need is unquote splice (~@) operator ?

9:06 Vinzent: jweiss_, don't think that slime have java support

9:06 pdk: zoldar, apply

9:06 zoldar: isn't do a special form ?

9:06 arnorhs: I've just never thought much about it, I might start a new vm and see how far I can go without it

9:06 pdk: (apply + 1 2 [3 4 5]) -> (+ 1 2 3 4 5)

9:06 zoldar: i mean (apply do body) instead of ~@body

9:07 pdk: i don't see why you'd do it that way

9:07 Dranik: zoldar, write a macro which transforms your quoted code

9:07 zoldar, sorry, not macro but a function

9:07 arnorhs: what about the java build tools, ant & maven. Would most clojure apps work without them? Doesn't lein depend on those?

9:07 Vinzent: zoldar, you can use ` in fns

9:08 pdk: ~ ` and ~@ can be used outside of macro definitions

9:08 clojurebot: macro are just a game with symbols

9:08 zoldar: Vinzent, ok I'll try

9:08 pdk: basically anywhere you could use '

9:10 zoldar: ok, got it, neat

9:17 mattmitchell: how can i do a file path join?

9:18 zoldar: mattmitchell, clojure.contrib.duck-streams/file-str

9:18 sgronblo: Any vim users? Is there an easy way to get these rainbow parentheses and syntax highlighting without these slime-whatevers?

9:18 mattmitchell: zoldar: thanks!

9:18 zoldar: mattmitchell, but it seems to return java.io.File already

9:21 fliebel: $seen tonyl

9:21 sexpbot: tonyl was last seen talking on #clojure 2 days and 16 hours ago.

9:23 pdk: easiest way is probably just to intall vimclojure sgronblo

9:23 fliebel: pdk: easy? it took me hours to figure out all the conflicting instructions for the config and nailgun.

9:24 pdk: i kinda gave up on the nailgun part of it too

9:24 though if he just wants a more clojure friendly text editor the base plugin does the job

9:24 sgronblo: pdk: but you can install vimclojure without bothering with this nailgun and stuff

9:24 ?

9:24 fliebel: you can

9:25 pdk: i just ignored nailgun since i already had back luck trying to make emacs + slime work on windows

9:25 either that or i'm that bad with emacs :p

9:25 bad luck even

9:25 zoldar: when I want to set an atoms contents to a completely new value, should I use reset! ? or are there cases where using (swap! foo #(fn [_] newval)) is preferred?

9:25 * fliebel needs to revise his vim setup

9:25 pdk: reset! is more concise

9:25 maybe if the fns you're using to alter the atom are being generated on the fly

9:26 fliebel: zoldar: reset!, but if you wanted to do what you did, you'd use constantly.

9:26 pdk: ,((constantly 1))

9:26 clojurebot: 1

9:27 zoldar: (swap! foo constantly 1) ?

9:28 fliebel: zoldar: That would swap foo with a function that returns… the previsou valua and 1 or whatever.

9:28 pdk: (constantly x) is shorthand for creating a function that just returns the same x every time

9:28 ,(constantly 1)

9:28 fliebel: &(swap! (atom 2) (constantly 1))

9:28 sexpbot: ⟹ 1

9:28 clojurebot: #<core$constantly$fn__3551 clojure.core$constantly$fn__3551@223be4>

9:28 pdk: ,#(1)

9:28 clojurebot: #<sandbox$eval108$fn__109 sandbox$eval108$fn__109@497536>

9:28 zoldar: ok, it seems that it doesn't make sense anyway; I just recall someone somewhere advising for using swap! over reset! in some cases. I can't recall the detials

9:28 ok, got it

9:29 pdk: we've seen a few insane suggestions from blog posts linked here before :p

9:29 zoldar: that's why I'm asking - to set the record straight :)

9:29 fliebel: zoldar: If you look at the source, it uses atomicreference. swap uses compareAndSet, whule reset! just uses set.

9:30 this means that reset! will have a lot less overhead.

9:30 pdk: swap! is p much for making changes to the atom relative to its current value

9:30 things like adding 1 to it etc, stuff where the original value is going to be an operand

9:31 ,(let [x

9:31 clojurebot: EOF while reading

9:31 pdk: ,(let [x (atom 1)] (swap! x inc) x)

9:31 clojurebot: #<Atom@d0005e: 2>

9:32 zoldar: I know, I just thought that maybe there's some merit to this, which I could be missing, like some marginal case in highly concurrent situations, but I see it isn't so

9:33 fliebel: zoldar: 2 paralel changes might leave behind a different result depending if you use swap or reset.

9:33 zoldar: fliebel, but it isn't predictable anyway

9:33 fliebel: with reset, the last change wins, while with swap, the first retries.

9:40 semperos_: say I have a merge-with like this

9:40 (merge-with (fn [v1 v2] (if (= "foo" v1) v1 v2)) m1 m2)

9:40 how would I use that function within a (dosync (alter...)) ?

9:43 I can understand the syntax for something like assoc-in, where the ref is the first param

9:43 (dosync (alter my-ref assoc-in [:foo :bar] "baz"))

9:43 jweiss_: is there really no help from slime to see the method signature of a java class's constructor? do i have to open up the source?

9:44 for instance if i type "(String. "

9:44 and i want to see all the types the string constr will take?

9:45 i notice the inspector gives sigs but not for constructors

9:45 i was thinking more like the minibuffer with clojure fns

9:45 that shows what args it takes

9:45 pjstadig: jweiss_: patches welcome :)

9:46 semperos_: I don't know how, but considering java classes can have a whole bunch of constructors, I just keep the javadoc handy

9:46 jweiss_: hm ok. i'd love to submit a patch, but not sure if i'm up to the task. just wanted to check that it hasn't been done so i can stop searching google :)

9:52 shortlord: there is nothing like a reverse operation of 'frequencies' built-in, is there?

9:53 semperos_: maybe a more general question is, how do I use functions with (alter) that take the value of the ref as the second param, instead of the first?

9:54 fliebel: shortlord: What would that do?

9:54 shortlord: fliebel: {:a 2, :b 1} -> (:a :a :b)

9:55 fliebel: shortlord: But maps are unordered… wel le me see...

9:55 zoldar: semperos_ : (alter foo #(somefun arg1 %)) ?

9:56 fliebel: &(mapcat #(repeat (val %) (key %)) (frequencies [:a :b :c :b :c :c]))

9:56 sexpbot: ⟹ (:a :b :b :c :c :c)

9:56 semperos_: zoldar: trying...

9:57 fliebel: shortlord: ^

9:57 shortlord: fliebel: yep, that's what I came up with as well, just wanted to make sure that there is nothing like that built in

9:58 fliebel: shortlord: I don't think so. Why would you need that?

10:00 shortlord: fliebel: well, the same question applies to frequencies, doesn't it? it's not too complex either, but is included in clojure.core. So I was wondering if something with the reverse effect was maybe included as well

10:01 fliebel: shortlord: Why do _you_ need it? I used frequencies a number of times, but never wondered if the opposite would be possible.

10:01 semperos_: zoldar: trying to use merge-with within (alter)

10:02 (dosync (alter my-ref (fn [m] (merge-with my-func m another-m))))

10:02 is what your suggestion looks like with that, but not working

10:02 zoldar: is another-m also a ref ?

10:02 semperos_: no, it's just a map

10:03 plain (merge-with my-func m1 m2) works fine, with regular maps

10:03 trying to get it right within a doref alter, because I want to use it with a ref

10:03 *dosync alter

10:04 shortlord: fliebel: I guess I don't really need it. I wanted to figure out the total number of ordered things (the map stores ordered things + amount), but that could also be done using reduce

10:04 zoldar: semperos_, what error do you get ?

10:04 semperos_: java.lang.String cannot be cast to java.util.Map

10:04 shortlord: if something like the reverse frequencies would have existed, I could have done (count (rev-frequencies map))

10:04 semperos_: stupid me

10:05 thanks for asking that, made me look harder

10:05 zoldar: so probably ref is string

10:05 semperos_: nah

10:05 zoldar: i mean contents

10:05 bartj: why is this an infinite loop ?

10:05 semperos_: another-m was a vector

10:05 bartj: , (doseq [i (range 10) j (range)] (println i j))

10:05 zoldar: uh

10:05 fliebel: shortlord: Ah, right. Yea, it seems all the data you might want out of the unfrequenced list is contained in the map.

10:05 clojurebot: Execution Timed Out

10:05 semperos_: I had used zipmap to create a new map from a couple of vectors

10:05 was mistakenly passing in the old vector (instead of the new map from zipmap) as the second map

10:05 thanks z

10:06 thanks zoldar

10:06 zoldar: semperos_, anyway you can use #(..) form instead of (fn [_] ...)

10:06 semperos_: yeah

10:06 but I already had an anonymous function inside my merge-with

10:06 was getting a bit hard to read :)

10:06 zoldar: ah

10:06 fliebel: bartj: doseq loops the inner range first, which is infinite.

10:06 bartj: oh :(

10:06 shortlord: fliebel: yep, right now I am using (reduce #(+ %1 (val %2)) 0 map-with-products)

10:06 bartj: I'll just move it to the first then :)

10:06 fliebel, the same is with for, I guess

10:07 fliebel: bartj: doseq and for are nested, not parallel.

10:07 bartj: oh

10:07 double oh

10:07 how can I iterate parallely, and then stop when one of them gets over ?

10:07 fliebel: sot i't go like 0,0 0,1 0,2 … 1,0 1,1 ...

10:07 map?

10:07 clojurebot: map is lazy

10:07 bartj: yeah

10:07 pdk: (doc dorun)

10:07 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. dorun can be used to force any effects. Walks through the successive nexts of the seq, does not retain the head and returns nil."

10:08 pdk: (doc doall)

10:08 clojurebot: "([coll] [n coll]); When lazy sequences are produced via functions that have side effects, any effects other than those needed to produce the first element in the seq do not occur until the seq is consumed. doall can be used to force any effects. Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time."

10:08 fliebel: &(map println [1 2 3] [4 5 6 7 8])

10:08 sexpbot: ⟹ (1 42 5nil 3 6nil nil)

10:08 pdk: you could iterate over the seq returned by map with doseq and execute the bulk of what you wanted to do each step in the body

10:09 bartj: yeah, I could do that

10:09 fliebel: &(map + [1 2 3] [4 5 6 7 8])

10:09 sexpbot: ⟹ (5 7 9)

10:10 bartj: is there "no" way apart from a map ?

10:10 fliebel: loop/recur...

10:11 bartj: I am returning stuff lazily

10:11 fliebel: bartj: What is wrong with map?

10:11 bartj: and loop/recur will require me to artificially create a new variable and store stuff in it

10:14 fliebel: bartj: ^

10:14 bartj: fliebel, I am trying that

10:14 fliebel: ok

10:14 bartj: fliebel, thank you for your time and answers

10:15 fliebel: :) have fun

10:24 edw: Anyone here use the ZeroMQ glue for Clojure? The destroy-socket fn throws an exception because there's no underlying destroy method on the Socket object. There is a close method. I do not have a lot of confidence is the clojure-zmq module, for this and other reasons...

10:42 bartj: ,mail

10:42 clojurebot: java.lang.Exception: Unable to resolve symbol: mail in this context

10:45 bsteuber: Hi everyone

10:45 Dranik: bsteuber, hello!

10:45 bsteuber: do you think it might be clever to make ^"foo" behave like ^{:doc "foo"} ?

10:46 seems reasonable to assume a string is mosten often used for documentation

10:48 wolverian: cd ..

10:48 ack.

10:49 edw: Is there a simple way to export constants in a namespace that are taken from a Java class?

10:51 bartj: edw, import-static ?

10:51 grr, why does sexpbot say I have a message

10:51 and how do I view it ?

10:53 edw: bartj: Hmm. I need them to be public. I'll just ask people to also import the Java classes in their code.

10:59 fliebel: bartj: type $mail, and he'll show you.

10:59 bartj: $mail

11:00 jweiss_: is there a simple way to call a java method given a list of args, similar to using a apply on a clojure fn?

11:01 bartj: fliebel, thank you

11:01 jweiss_: ,(apply System/getProperty ["a" "g"])

11:01 clojurebot: java.lang.Exception: Unable to find static field: getProperty in class java.lang.System

11:01 bartj: looks like someone sent me a mail

11:01 how about sending someone an email here?

11:01 that can be done using clojurebot ?

11:01 raek: jweiss_: clojure.lang.Reflector/invokeInstanceMethod

11:01 https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Reflector.java#L23

11:02 jweiss_: raek, what about static methods

11:02 fliebel: $mail bartj it is the same command.

11:02 sexpbot: Message saved.

11:02 raek: bartj: $mail is a feature of sexpbot, not clojurebot

11:02 jweiss_: raek: ah looks like that's in there too

11:02 raek: yup

11:02 bartj: $mail

11:03 fliebel, cool

11:06 raek: looks like there is a clojure.reflect.java namespace in 1.3. interesting.

11:07 jweiss_: ,(clojure.lang.Reflector/invokeStaticMethod System "getProperty" ["a" "b"])

11:07 clojurebot: java.lang.IllegalArgumentException: No matching method found: invokeStaticMethod

11:07 jweiss_: what's weird about this ^ is that the stack trace shows this exception is thrown BY invokeStaticMethod

11:07 i'd sorta understand if it said "no matching method: getProperty"

11:09 raek: ,clojure.lang.Reflector

11:09 clojurebot: clojure.lang.Reflector

11:10 raek: jweiss_: I think you need to call invokeStaticMethod with an array

11:11 jweiss_: raek: ah right. still that error message sucks

11:11 raek: there's also invokeStaticMehtodVariadic

11:12 but it's true... the reflector tried to find a suitable invokeStaticMethod method, but could not find any with a compatible type signature... ;-)

11:12 in this case, that method is involved on two different levels

11:13 mefesto: ,(clojure.lang.Reflector/invokeStaticMethod "java.lang.System" "getProperty" (into-array ["a" "b"]))

11:13 clojurebot: java.security.AccessControlException: access denied (java.util.PropertyPermission a read)

11:13 jweiss_: mefesto: yeah i got it to work, i just don't understand how the call to public static Object invokeStaticMethod(Class c, String methodName, Object[] args) throws Exception

11:13 worked at all when i passed it a vector.

11:14 afaik a vector is not an array.

11:14 oh wait

11:14 mefesto: it worked with a vector?

11:14 jweiss_: no

11:14 but i thought the error message sounded wrong

11:15 but raek is right, the invokeStaticMethod was actually used to call itself.

11:15 the inner invocation is what failed

11:19 jkdufair: how would i include a '.' in a GET request to a compojure route? I tried urlencoding it and also tried to read the clout src, but couldn't quite get it

11:19 i.e. http://localhost:8080/person/new/TheName/foo@bar.baz

11:20 it wants to treat the dot in the email as a separator

11:30 Vinzent: jkdufair, maybe "/person/new/:name/*"

11:30 mattmitchell: any opinions on clojure.test vs midje for testing?

11:30 fbru02_: mattmitchell: i use lazytest

11:30 jkdufair: Vinzent: thx. I'll try that

11:32 fliebel: mattmitchell: have you considered clojure.core/test? < joke; I have no idea what the function is doing ##test

11:32 &(doc test)

11:32 sexpbot: ⟹ "([v]); test [v] finds fn at key :test in var metadata and calls it, presuming failure will throw exception"

11:34 fliebel: What is the difference between all those testing frameworks? I mean, you but a bunch of assertions in a file, and see if they work.

11:36 semperos_: fliebel: here's stuart sierra's thoughts on his work on clojure.test and then lazytest: http://stuartsierra.com/2010/07/05/lazytest-status-report

11:37 he's blogged about it more than once, so that's one place to read

11:37 jkdufair: Vinzent: worked! thank you. also makes me realize i need to understand defroutes even better

11:39 Vinzent: jkdufair, np :)

11:40 edw: If you've written some simple glue to project foo, what should one call the code? clj-foo? clojure-foo?

11:43 jkdufair: looks like a custom regex is my friend for this problem: ["/user/:id", :id #"[0-9]+"]

11:47 Vinzent: btw, I have a trouble with appengine-magic. When saving new entity, I'm passing nil as a value of the key, and both save! and retrieve works fine, but key of retrieved entities still contains nil. Am I doing something wrong?

11:47 an example: http://paste.lisp.org/+2K2Q

11:50 jkdufair: I'm just letting appengine generate its own ids for me. perhaps try capturing the result of the save! shouldn't it provide you an id?

11:59 * ldh wishes he'd discovered appengine-magic before

11:59 Vinzent: jkdufair, no, it's nil too. It's weird that I can retrieve entity by the key, so entity saved properly, but value of the key field in retrieved record not setted. Looks like a bug, isn't it?

12:00 jkdufair: Vinzent: yeah it does, actually

12:01 does it happen in your local as well as at google?

12:02 Vinzent: haven't tested it yet

12:04 jkdufair: i'll try it on mine and see if it's doing the same here

12:10 Vinzent: jkdufair, same thing with dev_appserver.sh

12:11 jkdufair: ok. trying it out here

12:14 same thing here. can retrieve by id, but the :id slot is nil

12:15 btw, how do you run your tests using appengine-magic?

12:16 Vinzent: (use-fixtures :each (local-services)) just as sayed in readme

12:18 jkdufair: Vinzent: thx. missed that one

12:48 mduerksen: hmm, when i defrecord with a field named size, odd things can happen (clj1.3): when retrieving field like this, everything is fine: (:size obj). but when retrieving the field directly, it returns the number of fields: (.size obj)

12:50 amalloy: mduerksen: the . notation is overloaded between no-arg methods and fields

12:52 mduerksen: amalloy: shouldn't i be prevented from defining a record like this, or at least get a warning?

12:54 amalloy: mduerksen: maybe. i thought i saw somewhere a mechanism for resolving the difference, but i can't find it anymore

12:55 mduerksen: ok thanks amalloy. should i report this?

12:55 amalloy: but really i don't think you're supposed to be using (.field foo) notation for records anyway if you can help it

12:56 mduerksen: hmm, i like the . notation because its fast (and i need the speed in this case)

12:56 amalloy: mduerksen: so is (:field foo)

12:57 mduerksen: oh, so (:field foo) uses the records accessor?

12:57 amalloy: if the record is type-hinted, the compiler will resolve it for you; even if it's not, i believe there's some call-site caching that optimizes into (.field foo) until such time as you pass in a different class

12:57 mduerksen: that's interesting

13:00 amalloy: mduerksen: hm, for a trivial microbenchmark it looks like i might be wrong. a type-hinted record :field takes ~300% as long as .field

13:00 ask hiredman though, he's always telling me how i'm wrong about records

13:01 mduerksen: woah! when not type-hinted, (.field foo) is a magnitude *slower* than (:field foo) - i guess its because (.field foo) needs casting

13:01 amalloy: mduerksen: it doesn't just need casting

13:01 it needs reflection

13:01 it's horrible

13:01 mduerksen: thanks, thats what i meant

13:02 chouser: type hinting won't help :field, I'm pretty sure.

13:03 amalloy: but yeah, mduerksen, it looks like hinted .foo is 3 times faster than :foo, which is...2000x faster than an unhinted .foo

13:03 mduerksen: my microbenchmark looked like this: (defrecord Test [mine]) (def t (Test. 5)) (time (dotimes [n 1e6] (:mine t))) vs. (time (dotimes [n 1e6] (.mine t)))

13:03 amalloy: so you get most of the benefit just using :foo

13:04 mduerksen: yes, mine too

13:06 mduerksen: so it would be (.field foo) unhinted = 2000x (:field foo) = 6000x (.field foo) hinted. in that case, i will use (:field foo) normally and hinted (.field foo) in bottlenecks

13:07 hiredman: be sure not to just run it once for benchmarks, run it a few thousand times

13:08 mduerksen: hiredman: 1e6 should be enough to be stable

13:16 mefesto: anyone using clj-http ?

13:42 brehaut: mefesto: yeah

13:51 mefesto: brehaut: im trying to fetch binary data from a url any tips?

13:51 brehaut: seems like it keeps sending it to me as a string

13:52 edw: What does doing an HTTP HEAD on the URL return, content-type wise?

13:53 mefesto: edw: application/pdf

13:54 edw: Hmm. What are you using to fetch the URL?

13:54 mefesto: (client/get url {:query-params {"id" "blah"}})

13:56 hoping for an input-stream like in clj-apache-http

13:56 benreesman: i appreciate this is sort of a weird question for this channel, but does anyone have a suggestion for which php web framework will be most comfortable for someone coming from a clojure mindset?

13:57 edw: Why aren't you using clojure.contrib.http.agent?

13:58 mefesto: edw: no reason, just thought i'd give this lib a try

13:58 brehaut: edw: if you are also using ring, clj-http is a good fit

13:58 technomancy: isn't contrib's http client deprecated?

13:59 edw: I'm not surprised that a random HTTP client library stringifies ecerything.

13:59 * edw has no idea what ring is.

13:59 brehaut: edw: ring is the clojure web dev / http stack

13:59 mefesto: it's also v0.1.3 so maybe this is a bug ... although this is my first crack as using it so it's more likely my fault

13:59 brehaut: edw https://github.com/mmcgrana/ring

14:00 edw: Ah. I hope to never write another web app again.

14:00 mefesto: that's one thing that made me look at clj-http since middleware in ring is so handy and clj-http uses the same design i believe

14:00 brehaut: mefesto: it does

14:01 mefesto: the default clj-http.client/get etc wrap up a core api with a heap of common middlewares for you

14:01 sritchie: has anyone here used leiningen with textmate?

14:02 I use SLIME and emacs, but I need to ease a couple of guys into clojure, and they currently code in python, using textmate

14:02 mefesto: brehaut: just curious but is there an example of how one could wire up their own middleware into the request/response pipeline?

14:02 sritchie: any ideas on easing the learning curve?

14:02 brehaut: mefesto: https://github.com/getwoven/clj-http/blob/master/src/clj_http/client.clj

14:02 pdk: textmate has a clojure plugin

14:02 brehaut: mefesto: i think that page speaks for itself

14:02 pdk: failing that eclipse/netbeans/intelliJ all have their own as well

14:02 sritchie: pdk: it looks good, for the syntax, it just uses cake

14:03 pdk: sorry, I mean it uses cake, not leiningen

14:04 brehaut: mefesto: i wonder if the wrap-output-coercion middleware is converting it to a string

14:04 mefesto: brehaut: so if i had my own middleware function (e.g. myns/wrap-custom) is there a way to get that into the chain? or do i have to update the client/request in a binding?

14:04 brehaut: mefesto: if you pass :as :byte-array in your request options, does it work?

14:04 mefesto: make your own request, dont update the library binding

14:04 mefesto: brehaut: still a string

14:05 brehaut: thats surprising

14:06 mefesto: oh wait..

14:07 that works... sorry, i put :as :byte-array in the wrong place

14:07 clj-apache-http style :-\

14:07 brehaut: ah right. phew.

14:07 mefesto: brehaut: thanks for the help

14:08 brehaut: mefesto: no worries. i just read the code ;)

14:16 fliebel: I'm looking to split a url of unlimited length into pairs into a map. Would it be best to write a quick string split directly onto Ring, or does one of those router libs offer this?

14:19 so a/url/of/pairs -> ["a" "url" "of" "pairs"] -> {:a "url", :of, "pairs"}

14:23 amalloy: *baffled* what websites use the url that way instead of using ?query parameters?

14:23 fliebel: amalloy: wordpress?

14:24 no, not exactly that way...

14:25 they do tag/blah or something similar. I want to extend that to multiple criteria.

14:28 Is (apply array-map) a idiomatic way to turn a flat seq into a map? (into {}) expects pairs.

14:29 chouser: sure, apply array-map or hash-map

14:30 fliebel: chouser: Thanks. Please remember me of the difference. Something with guaranteed order and small lenghts?

14:31 I think someone told me before, but I can;t find it.

14:32 technomancy: fliebel: array-maps grow into hash-maps when they get large enough; array-maps preserve order

14:32 but in general you shouldn't care about the distinction between the two

14:34 amalloy: fliebel: (into {} (partition 2 blah)) if you wanted to let the runtime figure out whether to use arrays or hashes

14:34 fliebel: technomancy: Interesting idea… Around what length? Are we talking around hundreds of items, or just anything larger than a shopping list?

14:35 amalloy: fliebel: ten

14:35 &(class (into {} (partition 2 (range 8))))

14:35 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry

14:35 fliebel: amalloy: ten? not even 32? 32 is still the chunk size, is it?

14:35 clojurebot: amalloy: therfor I return [previous] if rest is empty

14:36 fliebel: amalloy: Same problem here ;)

14:36 amalloy: right, maps don't like seqs, they want vectors :P

14:36 &(class (into {} (map vec (partition 2 (range 8)))))

14:36 sexpbot: ⟹ clojure.lang.PersistentArrayMap

14:36 amalloy: &(class (into {} (map vec (partition 2 (range 22)))))

14:36 sexpbot: ⟹ clojure.lang.PersistentHashMap

14:37 fliebel: nice

14:37 but, ugh, what a fuss to to get the map

14:37 amalloy: indeed. for urls, array-map is probably the way to go

14:37 fliebel: I figured so to.

14:37 amalloy: clojurebot: thanks for your suggestion, but as usual it is irrelevant

14:37 clojurebot: Ik begrijp

14:37 technomancy: clojure will do the right thing either way

14:38 amalloy: technomancy: ?

14:38 fliebel: &

14:38 sexpbot: java.lang.Exception: EOF while reading

14:38 fliebel: &(class (apply array-map (range 1000)))

14:38 sexpbot: ⟹ clojure.lang.PersistentArrayMap

14:39 fliebel: but assoc-ing that returns a hash-map

14:39 I'm going to stare at the implementation for a while, to figure out why there is this distinction.

14:40 static final int HASHTABLE_THRESHOLD = 16

14:40 jcromartie: So I've been reading Out of the Tar Pit.

14:41 (uh oh)

14:42 semperos_: using an atom to store a map; I run two swap!s, one after the other

14:42 the first swap changes the value of a key in the map

14:43 fliebel: hm, array-map does what it says on the tin. a map backed by a plain old array. now, over to hash-map, to see why array-map is needed.

14:43 semperos_: the second does a merge-with to merge on a new map; the function passed to merge-with makes sure that, if a key has a particular value, it keeps that value instead of being replaced by the new map's

14:43 when I do this step-by-step at teh repl, it works fine

14:43 amalloy: fliebel: a linear scan is faster than the hashing overhead for small-enough maps

14:44 semperos_: when I do it within a (let) in a function, it fails, the merge-with function doesn't do anything, a plain merge is performed

14:44 any thoughts?

14:44 mefesto: semperos_: what if you combined both actions into a single function and just called that with swap! ?

14:44 fliebel: amalloy: I think you are right.

14:44 raek: semperos_: can you post the code somewhere?

14:44 amalloy: fliebel: i know i am right :)

14:44 semperos_: I can

14:45 mefesto: going to try your suggestion first

14:45 jcromartie: It seems like Clojure draws a lot from "Tar Pit" but there are no libs for the declarative languages used to define state, logic, and accidental useful state or control

14:46 fliebel: amalloy: I meant to say I was not even going to doubt it, the source code looks long, complicated, and mentions papers.

14:46 raek: if you want to keep the old values, can't you just do (merge new-map old-map)?

14:47 semperos_: raek: yes, actually; I was caught up thinking about the fact that swap! and friends all take the derefed value as a first argument

14:47 but I can just use an anon fn and move it

14:47 raek: thanks

14:47 still curious why merge-with wasn't working though

14:48 raek: (swap! a #(merge %2 %1) m) (swap! a #(merge % m)) (swap! a (partial merge m))

14:48 semperos_: yep

14:48 needed fresh eyes, thanks

14:50 jaskirat: hey guys, i have been trying to understand recursive macros with this exaple in the practical clojjure book, but i cant seem to get it right.

14:51 raek: macros where the expansion contains the macro symbol?

14:51 jaskirat: i am trying to write a simpe macro to convert (++ 1 2 3 4) to (+ 1 (+ 2 (+ 3 4)))

14:51 can you help me point out why this doesnt work

14:51 (defmacro ++ [& e] (if (>= 2 (count e)) `(+ ~@e) `(+ ~@(first e) (++ ~@(rest e)))))

14:51 amalloy: jaskirat: macros are really just functions that operate on, and return, lists

14:51 jaskirat: yep

14:52 fliebel: jaskirat: Have a look at the source of -> for inspiration.

14:52 jaskirat: oops

14:52 (defmacro ++ [& e] (if (>= 2 (count e)) `(+ ~@e) `(+ ~@(first e) (++ ~@(rest e)))))

14:52 links?

14:52 raek: so you want (++ 1 2 3 4) to expand into (+ 1 (++ 2 3 4)) and then into (+ 1 (+ 2 (++ 3 4))) and so on?

14:53 amalloy: $source ->

14:53 sexpbot: -> is http://is.gd/KrdckN

14:53 jaskirat: raek: yes

14:53 amalloy: thanks

14:53 raek: jaskirat: have you used macroexpand-1 ?

14:54 it's very useful for seing what your macro actually does

14:54 jaskirat: raek: yep it runs into a Don't know how to create ISeq from: java.lang.Integer

14:54 raek: jaskirat: I think ~@(first e) should be ~(first e)

14:55 jaskirat: raek: oh yeah ! because first doesnt return a list

14:55 raek: let me try!

14:55 mattmitchell: i have a quoted list like: '(double :key) and i'd like to grab the :key keyword, use it as a key on a hash that contains a number, and then apply it to double. How do I "eval" or execute double (the function) from a quoted form?

14:55 amalloy: &(reduce (partial list `+) [1 2 3 4])

14:55 sexpbot: ⟹ (clojure.core/+ (clojure.core/+ (clojure.core/+ 1 2) 3) 4)

14:56 jaskirat: raek: awesome :)

14:56 raek: thanks a lot

14:56 fliebel: amalloy: Nice one :)

14:56 mattmitchell: i found that eval works, but is that the right way?

14:56 amalloy: jaskirat: my version expands in the opposite direction, but you might find it useful

14:56 raek: mattmitchell: you could do something like [double :key] or (list double :key)

14:57 jaskirat: amalloy: thanks , i was just learning about macros and trying em out

14:57 raek: then you will have the double function as the first element, rather than the symbol 'double

14:57 amalloy: mattmitchell: you'll need to eval if it's in a quoted list. is there a reason you can't have [double :key] instead, storing the actual function "double"?

14:58 mattmitchell: amalloy raek: ahh ok. no, i didn't think about doing it like that.

14:58 raek: mattmitchell: it's not very common to need to use eval (in my experience). most of the time, there is a more simple way

14:58 mattmitchell: raek: ok good then. my instincts were on to something.

14:59 raek: ,(let [pair [double :a], m {:a 1, :b 2}] (let [[f k] pair] (f (get m k))))

15:00 clojurebot: 1.0

15:01 amalloy: jaskirat: for sure, it's just good to keep in mind that you can write macros with list-manipulation functions as well as syntax-quote, especially when the latter will look convoluted

15:03 jaskirat: amalloy: i am very new to clojure, so i am not really aware of all list manipulation functions as of yet. That was new to me.

15:04 amalloy: jaskirat: there are a lot of such functions; it takes a lot of time to know "all" of them. but reduce, map, and iterate will get you most of the way

15:04 jaskirat: amalloy: that example that i was trying to solve was straight out of "practical clojure" and was wrong in the book but i could not figure out the bug

15:05 fliebel: Hm, I'm planning to do a XML DSL tomorrow. Core idea is that tags are lists with :namespaced/keywords and metadata. It'll be implemented on top of SAX. If you have ideas to share or want to nudge me into the right/a more sane direction, now is the time :)

15:07 jaskirat: amalloy: actually i was aware of map / reduce but your combination of partial along with this was particularly new.

15:07 amalloy: jaskirat: yeah, partial is crazy

15:08 fliebel: amalloy: Why and when do you use partial over an anonymous function? I like partial, but I had some discussions with people who prefer @() at all times.

15:08 #() I mean

15:09 amalloy: fliebel: meh. you can't nest #()

15:09 partial is overly verbose and prone to abuse, so i don't use it too often, but it seemed appropriate here

15:10 i could have written instead ##(reduce #(list '+ %2 %1) [1 2 3 4]) and gotten the expansion order right, i think

15:10 sexpbot: ⟹ (+ 4 (+ 3 (+ 2 1)))

15:10 fliebel: amalloy: What abuse?

15:12 mattmitchell: how do you test whether or not something is a function? etc.. (function? (fn [])) => true

15:12 amalloy: mattmitchell: fn? or ifn?

15:12 fliebel: if you start writing things like (map (partial map (partial apply +) ...)) your code gets to be unreadable

15:12 mattmitchell: amalloy: arg sorry :) i tried fun? func? and function? but not fn?

15:12 fliebel: mattmitchell: Beware of ifn though ##(ifn :a)

15:12 sexpbot: java.lang.Exception: Unable to resolve symbol: ifn in this context

15:13 fliebel: &(ifn? :a)

15:13 sexpbot: ⟹ true

15:13 amalloy: better to break it up into a couple explicit functions

15:14 $findfn first true

15:14 sexpbot: java.lang.Exception: Unreadable form

15:14 amalloy: *blink*

15:14 well, bugger that, i guess i have some debugging to do

15:14 fliebel: what would that do?

15:14 amalloy: fliebel: search for functions that return true when called on clojure.core/first

15:15 fliebel: amalloy: Does it do some clerer introspection, or does it try 500 functions to find ones that return true?

15:15 amalloy: the latter

15:15 fliebel: expensive...

15:15 amalloy: fliebel: not really

15:16 $findfn [1 2 4 8] [8 4 2 1]

15:16 sexpbot: [clojure.core/rseq clojure.core/reverse]

15:16 fliebel: neat!

15:16 amalloy: see? takes less than a second, when it's not broken :P

15:17 sgronblo: heh thats pretty cool

15:17 fliebel: So next time I have someone ask for a function that transforms x into y, I can let sexpbot figure that out.

15:17 amalloy: Does it work for multiple arguments?

15:17 amalloy: fliebel: indeed, but it's still pretty limited. it won't find partition for turning a list into a group of pairs, because it needs an additional 2

15:18 $findfn 1 2 3 6

15:18 sexpbot: [clojure.core/+ clojure.core/*]

15:19 jaskirat: $findfn [1 2 3] 6

15:19 sexpbot: []

15:19 fliebel: amalloy: Yea, so it's limited to 1:1 matches, not the slightest fiddling.

15:19 amalloy: fliebel: yeah. i've pondered improving it somehow, but nothing seems clear or easy

15:20 jaskirat: $findfn [1 2 3] [6]

15:20 sexpbot: []

15:21 fliebel: $findfn + [1 2 3] 6

15:21 sexpbot: java.lang.Exception: Unreadable form

15:21 fliebel: hrm...

15:21 amalloy: fliebel: i think it doesn't like functions

15:22 and i think i know why too; i'll poke around at it

15:22 fliebel: $findfn #(+ %1 %2) [1 2 3] 6

15:22 sexpbot: java.lang.Exception: Unreadable form

15:22 Raynes: chouser: ping

15:23 amalloy: fliebel: if we're going to be spamming with sexpbot we should do it in #sexpbot

15:37 defn: any sign of stuart halloway's talk at clojure conj?

15:39 chouser: Raynes: pong

15:42 * defn just noticed clj-record

15:43 defn: yay for an activerecord-esque lib for clojure

15:44 Raynes: chouser: I've not yet been told how No Starch chooses tech reviewers, but the editor mentioned it, so I pointed out that you would be a good option if you were interested. Just thought I'd ask if you are and if so, if you could give me an email address to pass along, assuming they take my advice.

15:44 No pressure to do so. You were just the first person that came to mind.

15:48 chouser: Raynes: to review your book?

15:48 Raynes: Right.

15:48 They need a "hardcore Clojure guy".

15:48 I'm not sure if they pay reviewers, but they probably do.

15:49 At least, O'Reilly does.

15:50 chouser: Raynes: I use gmail -- you can guess my username. I'd like to know how long it is and when I would be able to start.

15:52 Raynes: chouser: I doubt the book will ever surpass 300 pages. The current draft is around 150 pages. At least, it is with my formatting. No clue what it'll be when they do whatever they do with it. I'll pass along your email address, and if he is interested, I'm sure he'll fill you in more throughly.

15:53 chouser: Raynes: thanks.

15:58 TobiasRaeder: hi :)

15:59 can anyone explain to me when someone would use comp instead of ->/->>? comp seems to do the same (atleast to me)

15:59 chouser: -> and ->> are macros. comp is a function.

15:59 amalloy: TobiasRaeder: comp is a function, -> are macros

15:59 * chouser grins

15:59 TobiasRaeder: good point :)

15:59 amalloy: chouser: that's what i get for pausing to confirm before i hit enter

16:00 chouser: heh

16:00 TobiasRaeder: http://blog.fogus.me/2010/09/28/thrush-in-clojure-redux/

16:00 amalloy: TobiasRaeder: eg, (map (comp square inc) (range)) is hange

16:00 hande

16:00 handy. damn it

16:00 fliebel: And… comp can't take extra arguments, unless with #(), right?

16:01 amalloy: fliebel: shhhhh, you'll awaken a monad evangelist

16:01 TobiasRaeder: :D thanks for the infos

16:01 * fliebel wonders what a monad is

16:02 sgronblo: me too

16:03 amalloy: they're generalizations at a level more abstract than function composition. i still haven't gotten my head around when they would be useful in my code

16:03 you can find a zillion tutorials of varying quality online

16:03 hiredman: a monad can be deconstructed into a protocol for passing arguments between functions and a protocol for binding names to values (which are really the same thing)

16:04 fliebel: Yea, there are to much monad tutorials out there. Maybe I should write one.

16:04 Chousuke: I wrote a toy protocol based monad interface once I think it's still somewhere on the internet :P

16:04 +.

16:05 amalloy: fliebel: nah. they're just like burritos

16:05 $google monads are like burritos

16:05 sexpbot: First out of 252 results is: The Universe of Discourse : Monads are like burritos

16:05 http://blog.plover.com/prog/burritos.html

16:05 * fliebel wonder what burritos are

16:05 amalloy: fliebel: mexican food. tacos

16:06 fliebel: oh, well, second paragraph, and he used another word I don;t know LO

16:06 (I need to stretch my fingers more when I reach to the right)

16:07 amalloy: facetious ~= joking

16:08 fliebel: amalloy: I was talking about functor

16:08 amalloy: fliebel: man, that's like the *third* paragraph

16:08 fliebel: amalloy: Dude, zero-indexed, you know ;)

16:09 * amalloy hangs his head in shame

16:10 * fliebel would have invented −1nth indexed array on the spot if he was wrong

16:13 jcromartie: Don't blubify Clojure by saying that you couldn't imagine why monads are useful :)

16:14 LauJensen: Morning guys

16:16 TobiasRaeder: hey lau :)

16:16 LauJensen: hey Tobias

16:16 fliebel: hey

16:18 LauJensen: How vulnerable is CQL to SQL injection? Are all strings I use escaped, or ca I use literal SQL in there?

16:18 LauJensen: fliebel: ClojureQL keeps you 100% safe. It automatically parameterizes all queries

16:18 fliebel: good :)

16:19 I asume there is a function for weird cases where you need real sql?

16:19 LauJensen: fliebel: Whereever possible I support literal strings, but if you need some really funky SQL, you need to submit a compiler for that backend

16:20 But it really does do most things

16:21 fliebel: okay :) I don't expect to encounter any of those cases with my limited sql knowledge. I have been meaning to try cql for a while now, but haven't done so yet. :(

16:23 LauJensen: I regularily get emails from people telling me how much they love it, so I assume its good :)

16:23 fliebel: :)

16:44 dnolen: I see two problems now w/ monads 1) not particularly efficient 2) inherently single-threaded. 1) seems like a hard problem to solve in the general case 2) can't do anything about that

16:51 Chousuke: dnolen: both 1 and 2 are false, unless you're talking about a specific implementation

16:52 any monad is free to combine operations in whichever manner it's programmed to do, and that includes running the ops in parallel.

16:53 at least, as far as I can tell, I'm not a monad expert either. :/

16:54 hiredman: the new composable async Task stuff in C# and VB.Net is built on a monadic interface

16:55 brehaut: point #2 is one rhickey has made before

16:56 hiredman: well, that is not correct

16:56 brehaut: http://clojure-log.n01se.net/date/2010-02-12.html#i70

16:57 hiredman: whats the link for?

16:57 brehaut: thats the previous discussion on the same

16:58 hiredman: if you are trying to convince me that rhickey said it, I believe you, but just because he said it, that does not make it correct

16:59 brehaut: of course it doesnt

16:59 hiredman: https://github.com/hiredman/die-geister is my take on the async Task stuff from C#

16:59 (also F# has async too)

17:00 brehaut: F#'s async is great

17:01 hiredman: right, the reason you can compose async tasks is Task is a monad

17:01 brehaut: yes.

17:01 hiredman: (I think the f# paper on them calls them joinads)

17:05 brehaut: amalloy: monads are more about generalised function application than composition; arrows are the generalised composition

17:06 opqdonut: isn

17:06 't Applicative generalised function application?

17:06 brehaut: depends how far you want to generalise

17:06 opqdonut: mhmm

17:06 hiredman: https://github.com/jduey/conduit

17:07 opqdonut: oh, this was #clojure

17:07 thought for a moment I was in #haskell

17:07 hiredman: :D

17:08 brehaut: its the armchair categorists meetup today

17:08 hiredman: (conduit is built on arrows)

17:09 brehaut: frightening and awesome :)

17:09 hiredman: we use it at work for our async messaging

17:09 actually clojurebot uses it now too

17:10 for streaming processing in clojurebot's case, not async messaging

17:17 brehaut: i dont know how i missed jim duey's stream articles

17:17 they are really good

17:24 dnolen: http://www.mail-archive.com/haskell-cafe@haskell.org/msg71116.html

17:24 monads are sequenced, not commutative.

17:26 http://www.valuedlessons.com/2008/03/why-are-my-monads-so-slow.html

17:26 hiredman: dnolen: if I disgree more, will you spend more time googling about it?

17:27 dnolen: hiredman: why google when you can point me to better articles?

17:28 hiredman: dnolen: why would I do that?

17:29 dnolen: async ops still implied explicit sequencing, and that not a general concurrent framework anyhow.

17:29 or rather it has a lot of assumptions about ho to solve the problem right?

17:30 hiredman: if you look at die-geister it allows you to join multiple async tasks into a single async task

17:30 while not explicitly a monad the implementation is very similar to something like, uh, whats it called, fmap? for the list monad

17:30 brehaut: functor

17:32 dnolen: for example commute in Clojure's STM is an interesting solution to some problems, a monad can't capture that as far as I can tell.

17:33 hiredman: commute is not functional, why would you want to use that in a functional construct like a monad?

17:36 dnolen: hiredman: except people use monads to model state

17:36 hiredman: dnolen: they use monads to model state in a functional setting

17:37 refs are mutable and not functional, so why would you do that?

17:37 Chousuke: state is not all monads are good for.

17:37 dnolen: Chousuke: I know that.

17:37 hiredman: (actually haskell's STM is exposed in a monad because they hide all mutable things in monads)

17:40 brehaut: hiredman: i think geister might be closer to an applicative than functor?

17:40 dnolen: http://www.mail-archive.com/haskell-cafe@haskell.org/msg82109.html

17:41 hiredman: brehaut: *shrug*

17:41 dnolen: in anycase, monads - big tradeoffs as with all things.

17:42 brehaut: the difference is that as well as being able to apply functions to thinks in the async context, it also has a way to apply functions that are in async contexts to other async contexts resulting in a new async context?

17:42 hiredman: dnolen: the issue there is the haskell type system doesn't express the constraits of being communicative

17:42 brehaut: that is ultimately bind

17:43 bind is like a protocol for binding names to values

17:43 brehaut: hiredman: its slightly less than bind i thing

17:43 hiredman: it is less then bind because I can't enforce the type

17:43 brehaut: hiredman: in haskell applicative is also less than bind even though they can enforce type

17:44 hiredman: I see

17:44 but I want to enforce the type

17:44 I just can't

17:44 brehaut: the type of yeh applicative operator (<*>) is f (a -> b) -> f a -> f b

17:44 vs bind which is m a -> (a -> m b) -> m b

17:45 hiredman: if you are looking at the die-geister source I am very proud of blet and Bindable

17:45 realizing I could do that as a protocol was so cool

17:45 brehaut: i am and agreed

17:45 i liek the extension of deref to bindable too

17:46 i cant find blet though

17:46 hiredman: maybe I never commited it

17:47 it's a macro that expands to a let that calls bind on everything before binding it to a name

17:48 (with the default extension of Bindable to Object being identity)

17:48 dnolen: my miniKanren work also made me suspect things like this - http://www.haskell.org/haskellwiki/Performance/Monads

17:48 unrolling monads

17:49 brehaut: dnolen: even simple state-m definitions explode into frightening amounts of funcalling; adding any transformers on top is even more horrific

17:50 hiredman: I am by no means advocating monads everywhere, I am just saying they are extremely useful as a basis for library writers to ensure the composability of their code

17:50 and that monads do not imply single threads of execution

17:57 brehaut: hiredman: re: applicitve and monad, i think monadic for can be defined for any applicative in terms as a >>= f = (pure f) <*> a.

17:57 which muddies the waters between applicative and monad even more

17:57 (pure being the applicative function to take something and put it into the appropriate applicative type0

19:53 sritchie: does anyone have any advice on how to encode a float array as a byte array?

19:54 I can map the array to a seq -- I'm just not sure how to get a byte representation of my float, for the map

20:04 amalloy: sritchie: make a ByteArrayOutputStream, wrap it in a DataOutput, write floats to it, then read them as bytes; or do the equivalent with buffers

20:04 would be my hacky solution

20:04 sritchie: amalloy: this is sort of a hack, in any case -- hadoop can stream byte arrays, but not float arrays

20:05 amalloy: I'll go check out io for outputstream

20:06 amalloy: i don't think c.j.io will have the necessary tools, you'll have to actually use java.io.XXX stuff

20:06 sritchie: amalloy: yeah, looks like it

20:06 amalloy: it's odd, I'm searching all over, and this doesn't seem to be something anyone's been vocal about yet

20:07 passing anything but byte arrays or heavy custom objects around

20:07 or maybe it's considered trivial, who knows

20:07 amalloy: sritchie: hadoop will handle floats for you, won't it?

20:08 sritchie: amalloy: yes, but not float arrays

20:08 amalloy: byte arrays can be wrapped in BytesWritable quite easily,

20:08 amalloy: but the underlying hadoop model is that most parts of the system deal with "data" they don't know anything about, which is what BytesWritable is for

20:08 "here is a chunk of data, sritchie plz deal with it cause it is too confusing for the hadoop internals"

20:10 sritchie: amalloy: yeah, that's true - I do that for an inputformat I wrote that takes a single file at a time, rather than cutting text into lines, etc

20:10 by opening a stream, and using IOUtils.readFully

20:11 amalloy: so it sounds like your suggestion is the way to go, just copying that approach by streaming out these floats

20:12 amalloy: that's hadoop's IOUtils, btw

20:13 amalloy: sritchie: hadoop's, or apache commons? it surprises me that hadoop would expose a way to read a file fully, with its "big data" approach

20:13 sritchie: hadoop's, actually -- http://bit.ly/h1JYXT

20:13 amalloy: fair enough

20:38 sritchie: amalloy_: so it looks like cascading does support byte arrays natively -- one just has to add the serialization beforehand

20:38 now, I just need to find out how to do that in cascalog

21:28 joshua__: $findfn nil false

21:28 sexpbot: [clojure.core/keyword? clojure.core/chunked-seq? clojure.core/sequential? clojure.core/fn? clojure.core/not= clojure.core/string? clojure.core/sorted? clojure.core/false? clojure.core/true? clojure.core/symbol? clojure.core/number? clojure.core/integer? clojure.core/... http://gist.github.com/812141

22:24 trptcolin: so i'm teaching a clojure course in april - geared more towards the beginner end of the spectrum than most in the #clojure irc crowd

22:24 any tips on promotion?

22:26 details: http://8thlight.com/courses/2-clojure-functional-programming-on-the-jvm

22:29 amalloy: trptcolin: i wrote a blog post with that target audience last month; you might find some stuff you can use at http://hubpages.com/hub/What-is-Clojure

22:30 trptcolin: nice, that looks great!

22:31 amalloy: trptcolin: go spread links all over the internet; my coworker (at hubpages) needs to be constantly reminded that clojure generates more traffic than his silly hobbies :)

22:31 trptcolin: i do think i have a decent approach/handle on getting the material across once in the class, it's mostly getting people *to* the class i'm unsure about

22:32 good point. i don't want to come across as spammy though

22:32 amalloy: trptcolin: i kid, i kid. don't spam me

22:32 or for me, rather

22:32 trptcolin: LOL

22:34 brehaut: trptcolin: just stay clear of fact and fib ;)

22:35 trptcolin: what? but how will i teach the joys of avoiding StackOverflowError ;)

22:36 brehaut: haha

22:36 amalloy: brehaut: haskell has spoiled you so much that you don't think (defn ! [n] (reduce * (range 1 (inc n)))) is elegant?

22:37 brehaut: amalloy: i love a good hylomorphism as much as the next nerd, but i dot think FP noobs care :P

22:37 amalloy: aha. yes, that is certainly true

22:37 trptcolin: oh snap you brought out the *morphism in #clojure

22:37 amalloy: lol

22:37 brehaut: it was worse earlier

22:38 amalloy: trptcolin: brehaut is from the wrong side of the tracks

22:38 brehaut: there was a spontaneous meeting of the armchair categorists

22:38 yeah python and javascript ;)

22:39 amalloy: also, you can hardly talk. all that point free? thats certainly from the dark side ;)

22:44 amalloy: talking of point free, have you looked at conduit ?

22:45 amalloy: brehaut: i caught a link to it from twitter on the bus ride home, but barely glanced at it. the readme isn't very compelling :P

22:45 brehaut: hah

22:46 its comp and juxt souped up with nos and a rocket booster

22:57 amalloy: brehaut: you should see the absolutely disgusting parsing functions i wrote for my markov bot. i really need to learn fnparse or parsec or something

22:57 brehaut: you absolutely do. parsec is the most elegant but fnparse looks solid

22:58 i wrote a parser combinator library for python (its easy to write excruciatingly slow parser) and it made a bunch of day to day tasks a world easier

23:00 need to find the time to learn fn-parse myself

23:16 amalloy: brehaut: when you do, please write up some cliff notes for me

23:16 brehaut: sure thing :)

23:16 amalloy: cause you're clearly my secretary

23:16 brehaut: clearly

23:17 it'll makea good blog post anyways

Logging service provided by n01se.net