#clojure log - Oct 25 2010

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

0:33 amalloy: ymasory, dsantiago: technically not just the name after &. the last argument can have further destructuring

0:36 ,((fn [a b & {c :name}] [a b c]) 1 2 :name "steve" :age "paul")

0:36 clojurebot: [1 2 "steve"]

0:40 amalloy: heh. i guess paul isn't a good age. got distracted there :P

0:48 Derander: WORDPRESSSSSSS

0:52 amalloy: is that so?

1:18 rdeshpande: yo

1:23 amalloy: oi

1:27 jackdempsey: hehe

1:27 amalloy: i turned "paul" just the other day

1:27 amalloy: haha, well, i take back my apology then

1:30 jackdempsey: hmm, a little unclear on how that destructuring works

1:30 ,((fn [a b & {c :age}] [a b c]) 1 2 :name "steve" :age "paul")

1:30 clojurebot: [1 2 "paul"]

1:31 jackdempsey: amalloy: so & says "take the rest of the args and stick them in the next thing

1:31 amalloy: jackdempsey: yep

1:31 jackdempsey: and this next thing just happens to be a map

1:31 amalloy: yep. sneaky, innit?

1:31 jackdempsey: so

1:31 hm

1:31 heh

1:32 i think i get destructuring normally

1:32 amalloy: heh. "normally"

1:32 jackdempsey: but this case seems a little different

1:32 haha

1:32 amalloy: just wait. when you get this i'll show you some more trickery

1:32 jackdempsey: ,((fn [a b & c ] [a b c]) 1 2 :name "steve" :age "paul")

1:32 clojurebot: [1 2 (:name "steve" :age "paul")]

1:33 jackdempsey: k that makes sense

1:33 but to make sure i'm calling things the correct names: (:name "steve" :age "paul") is a .....list at that point?

1:33 amalloy: it's a seq. i think whether it's a list or a vector or whatever is none of our business

1:34 jackdempsey: k so & foo takes the rest of the args and puts them in a seq referred to by symbol foo

1:34 amalloy: right

1:34 ,((fn [a b & c ] [a b c (class c)]) 1 2 :name "steve" :age "paul")

1:34 clojurebot: [1 2 (:name "steve" :age "paul") clojure.lang.ArraySeq]

1:34 jackdempsey: ah

1:35 so it almost seems like it should be & {:age}

1:35 why {c :age}

1:35 amalloy: you have to give it a binding

1:35 a way to refer to it inside the function

1:35 jackdempsey: c to name the arg and { ... :age} to destructure it?

1:35 amalloy: right!

1:35 jackdempsey: ,((fn [a b & {:age c}] [a b c]) 1 2 :name "steve" :age "paul")

1:35 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: :age

1:36 jackdempsey: aha

1:36 Adamant: jackdempsey: how's your left hook?

1:36 :P

1:36 jackdempsey: Adamant: not too shabby... a bit rusty given the whole "being dead a couple decades" thing :-D

1:37 Adamant: why, you could lick any man alive at the time, I don't see how being dead would make any difference :P

1:37 jackdempsey: hehe

1:37 man, watching IRT deadliest roads.....these drivers are insane

1:37 Adamant: jackdempsey: your real name or just a pseudonym? (in either case, someone had good taste :P)

1:38 jackdempsey: hehe, john by birth, but was too convenient to not go as jack

1:38 Adamant: ah

1:38 :)

1:38 yeah that road in South America is crazy

1:39 jackdempsey: ,((fn [a b & [foo & bam] [a b foo bam]) 1 2 :name "steve" :age "paul")

1:39 clojurebot: Unmatched delimiter: )

1:39 jackdempsey: ,((fn [a b & [foo bam] [a b foo bam]) 1 2 :name "steve" :age "paul")

1:39 clojurebot: Unmatched delimiter: )

1:39 jackdempsey: hm

1:39 amalloy: ,((fn [a b & [foo & bam]] [a b foo bam]) 1 2 :name "steve" :age "paul")

1:39 clojurebot: [1 2 :name ("steve" :age "paul")]

1:40 jackdempsey: off to a repl to hide my f'ups :-D

1:40 hmm

1:40 Adamant: if clojurebot does PM that could work

1:40 amalloy: he does

1:40 jackdempsey: huh, gotta read that again, don't see the difference

1:40 amalloy: you missed a ]

1:40 in the arglist

1:40 jackdempsey: ahh i see

1:41 interesting

1:41 so any tips on the destructing piece in the sense that: the structure you use to destructure needs to be _____ with the structure it's trying to destruct?

1:41 good lord that's a mouthful

1:42 amalloy: must be an earful too, cause i don't think it got through my ear to my brain. try again?

1:42 jackdempsey: e.g. i understand that a map works to destructure a map...and a vector can work on a seq....but it's a bit jumbled to me

1:42 heh

1:42 is there a good place to read on how/what i can use to destructure things?

1:43 amalloy: hmmm, i think ss has a good blog post on it, and JoC definitely has a nice entry

1:43 http://stuartsierra.com/2010/01/15/keyword-arguments-in-clojure is not *quite* relevant, but probably helpful

1:44 jackdempsey: cool. so now that i sorta/kinda get it...what was that cooler bit you wanted to show me?

1:44 amalloy: haha, i was gonna show you :or and :keys

1:46 jackdempsey: ok

1:46 amalloy: ,((fn [a b & {c :name d :age :or {d 10}}] [a b c d]) 1 2 :name "steve")

1:46 clojurebot: [1 2 "steve" 10]

1:47 jackdempsey: yeah

1:47 that makes sense

1:47 so

1:48 the {c :name} bit is correctly thought of as binding the {third-arg :name} to c and {third-arg :age} to d

1:48 except :age doesn't exist, so give it a default value of 10

1:48 amalloy: *nod* i think that's about right

1:49 ,((fn [{:keys [a b c d]] [a b c d]) {:a 1, :c 8})

1:49 clojurebot: Unmatched delimiter: ]

1:49 amalloy: ,((fn [{:keys [a b c d]}] [a b c d]) {:a 1, :c 8})

1:49 jackdempsey: i guess the final bit is being crystal on how & {c :name} turns into binding :name from the arg into c. it's like you're using a familiar form but not the same call semantics

1:49 clojurebot: [1 nil 8 nil]

1:49 jackdempsey: which would make me think i'm calling :name on c

1:49 lol the face

1:50 nice, yea i've seen :keys a little. is it used much in practice?

1:50 amalloy: hah, i dunno. i don't do a lot of anything, in practice

1:50 yeah, the fact that {a :name} rather than {:name a} is used for destructuring is a bit confusing

1:51 but it's so that things like :keys, :or, and so forth can't possibly be "normal" destructuring

1:51 kryft: Are there any vimpulse users around, btw?

1:51 amalloy: because :or is an illegal variable name

1:52 jackdempsey: hmm

1:55 amalloy: there are also :strings and :symbols equivalent to :keys. i've never used them, so they might be :strs and :syms or something

1:55 jackdempsey: cool

1:55 LauJensen: Morning all

1:55 amalloy: morning LauJensen

1:55 jackdempsey: ah

1:55 The keys of the binding map are the local variables you want to create. The values of the binding map are keys in the initialization expression. The locals will be bound to the values of corresponding keys.

1:55 that helps

1:56 amalloy: good, good

1:56 vibrant: morning

1:58 jackdempsey: ha :keys reminds me of explode or whatever that was in php

1:59 that took a hash and made locals from the keys in it

1:59 amalloy: oh blech. thank god i haven't run into that yet

2:00 hey LauJensen, since you got so sad yesterday i went and read your blog post about the orbital simulator, and i don't think you're right about the anonymous functions in distance/vector

2:00 LauJensen: amalloy: I dont remember being sad yesterday, and yes you're right about the anon fn, I spoke too soon

2:00 (read the comments)

2:00 amalloy: ah. you were "offended" i didn't follow your blog

2:01 LauJensen: yea that was a joke old chap

2:03 amalloy: hence my "scare quotes"

2:03 vibrant: so how do i represent 'objects' in clojure? like i na game i have a player, i created a hash-map for him and def'ed it to a global variable - how do i modify that map now?

2:05 LauJensen: ,(let [player (atom {:health 100 :name "Frank"})] (swap! player update-in [:health] dec))

2:06 clojurebot: {:health 99, :name "Frank"}

2:06 LauJensen: vibrant: Get familiar with Clojures reference types. For a game you might want refs instead of atoms

2:07 amalloy: LauJensen: i was going to suggest passing the player around instead of making him a global. seems a lot more functional to me. i assume you have a good reason for your approach, though; what is it?

2:07 vibrant: LauJensen: yeah I'll get there. now I just managed to boot up clj-processing and I'm experimenting with the base stuff and learning Clojure in the meantime :)

2:07 LauJensen: amalloy: Your idea is better for something like Pacman I suppose, though for a more complex game, the pain of passing everything stateful around in args, not to mention the performance hit would be counterproductive

2:08 Generally, a great strength of Clojure, is to handle inherently stateful tasks correctly. Ie. not pretending there is no state

2:09 amalloy: is there really much of a performance hit? it seems like swap! is going to have to create new objects and so on anyway, so the only hit seems to be passing around some pointers

2:11 i may be biased because my "game" does a lot of backtracking depth-first search, so i want to have old states available

2:13 LauJensen: amalloy: Well. I cant think of a one-size fits all answer re performance. The two hits you take are allocation and subsequent GC. Typically I think we see more seq traversal in programs that pass everything around. Though I might just be imaging that

2:14 kryft: LauJensen: Is there a big performance hit from seq traversal?

2:14 amalloy: i guess you do get more allocation passing stuff around, if you want to do deeply-nested modifications (eg changing the player's pet's hair color)

2:15 LauJensen: kryft: something like (-> this-seq map filter remove) etc, generates n number of seqs where n is the number of items in the list. However subsequently swapping that into an atom doesnt give a large overhead

2:22 amalloy: I guess in most cases, the only measurable performance diff, is whether or not you resort to transients, arrays or pods

2:22 amalloy: heh

2:22 yayitswei: when you guys get a chance, could you help me rewrite my recursive group-by function in idiomatic clojure? http://gist.github.com/644489

2:26 amalloy: yayitswei: you can get rid of the yucky first/rest with destructuring

2:26 LauJensen: ,(reduce #(let [[d m y] %2] (assoc %1 m (conj (%1 m []) [d m y]))) {} [[30 9 2010] [30 10 2010] [31 10 2010]])

2:26 clojurebot: {10 [[30 10 2010] [31 10 2010]], 9 [[30 9 2010]]}

2:26 amalloy: (loop [t s [f & fs] starting-fns] (use f and fs))

2:27 LauJensen: or I guess you could do something like that

2:27 amalloy: you'll be surprised to learn that such destructuring is much slower than first/rest/next

2:27 amalloy: indeed i will be surprised, LauJensen!

2:27 LauJensen: Even if you have to call first/rest 2 or 3 times, it will still be faster

2:28 yayitswei: vibrant: btw, I'm reading Stuart Halloway's book and he has a good example on Clojure snake using refs: http://github.com/stuarthalloway/programming-clojure/blob/master/examples/snake.clj

2:28 amalloy: LauJensen: your solution does a different thing than his function, though

2:28 LauJensen: amalloy: you mean in that its not recursive+

2:29 amalloy: maybe; i'm not sure what you mean. he seems to want nested maps for each grouping function

2:30 yayitswei: wow your versions are so much more dense

2:30 amalloy: yes, I believe that's what I want, trying it now

2:30 LauJensen: amalloy: of you're right, he's passing 2 f's

2:31 amalloy: LauJensen: i'm sure using reduce will be more idiomatic and/or better, but i didn't want to try and figure out how the function worked so i just pointed out a nice-looking fix

2:32 LauJensen: sure, so now he has 2 options :)

2:32 yayitswei: ,(doc use)

2:32 clojurebot: "([& args]); Like 'require, but also refers to each lib's namespace using clojure.core/refer. Use :use in the ns macro in preference to calling this directly. 'use accepts additional options in libsp...

2:32 yayitswei: interesting usage of 'use'

2:34 LauJensen: amalloy: I think you confused the man though

2:34 yayitswei: oh wait, that's pseudocode

2:36 amalloy: LauJensen: you're right, i should have used more parens and %s. that helped make your example more readable :)

2:37 LauJensen: ah you resort to mocking now do you? :D

2:38 amalloy: yeah, i gave up on actually looking smarter a while ago

2:39 yayitswei: amalloy: you're right though, I did want a nested hash. it took me a while to digest yours and Lau's suggestions

3:01 LauJensen: yayitswei: I understand why amalloys was hard to digest, but mine was quite elegant was it not? :D

3:02 amalloy: *laugh*

3:06 LauJensen: Here's a nested version

3:06 ,(for [f (list first second)] (reduce #(assoc %1 (f %2) (conj (%1 (f %2) []) %2)) {} [[30 9 2010] [30 10 2010] [31 10 2010]]))

3:06 clojurebot: ({31 [[31 10 2010]], 30 [[30 9 2010] [30 10 2010]]} {10 [[30 10 2010] [31 10 2010]], 9 [[30 9 2010]]})

3:10 amalloy: well, now that LauJensen has proved he's the best i'm off to bed

3:11 night folks

3:11 yayitswei: LauJensen: ah, thanks! very much appreciated. amalloy too :D

3:11 LauJensen: amalloy: dont forget to follow bestinclass.dk, sleep tight

3:11 yayitswei: night

3:11 amalloy: haha

3:11 LauJensen: :D

3:21 Nafai: Is there an easy way to call out to another process from within my clojure code?

3:22 LauJensen: Nafai: elaborate

3:23 Nafai: I want to get the output of an external program and then process it in Clojure

3:23 It's not something I've ever had to do in Java either

3:23 LauJensen: ,(doc sh)

3:23 clojurebot: It's greek to me.

3:23 LauJensen: Nafai: In contrib there's an 'sh' function, (sh "ls" "-l") will return a string, representing the output from ls -l

3:24 Nafai: Sweet, thanks.

3:24 LauJensen: np

3:43 cpfr: Hey is there a nice way to do introspection on java class instances

3:49 hoeck: cpfr: bean?

3:49 ,(bean "foo")

3:49 clojurebot: {:empty false, :class java.lang.String, :bytes #<byte[] [B@1d4ea6c>}

3:53 cpfr: all bean is telling me is the class

3:55 hoeck: cpfr: it uses public fields only, yes

3:56 cpfr: but this class has to have some public fields or methods

3:56 how else would it useful

3:57 hoeck: bean only creates a map of the class public fields

3:59 jarpiain: no, bean calls the methods named getFoo() and isFoo() and returns a map of the results

3:59 hoeck: jarpiain: sorry, you're right, lived too long in clojure land

4:43 jave: hello

4:44 I'm having difficulty setting headers in a compojure response

4:45 AWizzArd: jave: how do you try to do it?

4:46 jave: (GET "/header" [] {:headers {"Content-Type" "image/svg+xml"} :body "body"})

4:47 AWizzArd: (defn handler [request] ... [{:headers {"Content-Type" "application/json"}} "<html><head></head><body>Hallo Leute</body></html>"])

4:47 I return a vector of two elements.

4:48 jave: hmm

4:48 AWizzArd: The first, a map, only contains one key/value pair, and the second is the body string.

4:48 Try if this works for you.

4:49 jave: ok

4:54 xkb: if this is the input: (MyMona.core/draw-polygon graphics {:color {:red 55, :green 2, :blue 62, :alpha 231}, :points [{:x 121, :y 89} {:x 102, :y 17} {:x 3, :y 17} {:x 46, :y 82} {:x 150, :y 6}]}) How would I get :points using destructuring?

4:56 I'm using 2 nth's now

4:56 really ugly and sometimes returns errors on persistenvector not being able to do nth :?

4:57 LauJensen: java (content-type (response x y z) "image/svg+xml")

4:57 jave even

4:58 hoeck: xkb: (let [{c :color p :points} ...])

4:59 xkb: hoeck: even if :points is nested in the seq?

4:59 hoeck: (let [{c :color [p0 p1 p2 p3 p5 :as p] :points} ...])

4:59 or {[p0 p1 & pn :as p] :points]} ..

5:00 xkb: let me try it in the repl

5:01 hoeck: and to get the x and y of each point: (let [{[{x0 :x y0 :y} {x1 :x y1 :y}] :points} ...])

5:02 xkb: Thanks, Ill tinker around with it

5:02 hoeck: xkb: basically two rules, maps are destructured by writing the symbol to bind to first, then the key

5:03 xkb: and for vectors, just write the structure of the vector on the left side of the let :)

5:04 xkb: this explains all the details: http://clojure.org/special_forms#Special%20Forms--%28let%20[bindings*%20]%20exprs*%29

5:04 xkb: cool! nice link

5:05 got alot of inspiration to rewrite my code at the conj :)

5:48 ordnungswidrig: how can I get the ns of a function? (->> foo meta :ns) only works for fn hold in a var, not for reduce, e.g.

5:50 raek: ordnungswidrig: if you have the symbol, you can use 'resolve'

5:50 ,(resolve 'conj)

5:50 clojurebot: #'clojure.core/conj

5:50 ordnungswidrig: raek: I need the other way round

5:50 Chousuke: a function might not have a name

5:50 hmm

5:50 ordnungswidrig: Chousuke: ok, for those that have a name

5:50 Chousuke: ,(meta (fn []))

5:50 clojurebot: nil

5:50 ordnungswidrig: ,(meta reduce)

5:51 clojurebot: {:line 786}

5:51 raek: ,(meta conj)

5:51 clojurebot: {:line 77}

5:51 ordnungswidrig: or will clojure.core map to the empty ns?

5:51 raek: the function is unaware of the name of any var pointing to it

5:51 Chousuke: I suppose the function might not even have a namespace

5:52 it could be an IFn instance passed to you from some java user.

5:52 ordnungswidrig: Chousuke: I see

5:52 Chousuke: but the var has a name

5:52 and an ns

6:07 jave: how does compojure routes relate to ring handlers?

6:07 basically I'm now trying something like this, but its not working: (ring.util.response/content-type (GET "/header" [] (overview)) "image/svg+xml")

6:29 AWizzArd: ordnungswidrig: isn't the NS on the meta data?

6:29 jave: did it work?

6:30 you did not give feedback so far ;)

6:31 jave: AWizzArd: sorry....

6:32 it didnt work

6:32 I'm scratching my head here

6:35 AWizzArd: Maybe the behaviour changed. I am using an older version of Compojure.

6:35 jave: yes maybe

6:42 raek: jave: I'm not sure you can attach middleware that way

6:43 jave: problem is there is so many conflicting docs on compojure because of the many revisions

6:43 raek: it seems like you have to wrap the whole routes thingy in the middleware, rather than just the GET part

6:43 jave: I would recommend Moustache

6:43 the docs are very clear

6:43 jave: ok

6:44 but does moustache replace compojure, or what is the relationship?

6:44 raek: moustache is a routing lib

6:44 so it replaces defroutes

6:45 jave: ok

6:45 raek: you use it with ring as I guess you use compojure with ring

6:45 jave: so, what would my simple case look like then? I just want to set the content-type header

6:46 raek: using middleware is very simple

6:46 http://gist.github.com/644761

6:47 that is what I have in one of my projects

6:47 the (app ...) form creates a ring handler

6:47 you can prefix you routes with any number of middlewares

6:48 jave: cool ill have a look

6:48 raek: here's the moustache docs

6:48 http://github.com/cgrand/moustache

6:48 if you are used to reading grammars, you'll love this: http://moustache.cgrand.net/syntax.html

7:00 bartj: chouser, does clojure-jna also support calling third-party c++ libraries ?

7:00 chouser, from Clojure that is

7:48 _na_ka_na_: Hi, can I rely on using (:sigs AProtocol) to create me helper macros?

7:48 Hi, can I rely on using (:sigs AProtocol) to create me helper macros?

7:48 or is there some other way to extract fn specs from a protocol

8:16 chouser: _na_ka_na_: I don't think it's documented anywhere, so that detail could probably change without warning.

8:17 but would likely be replaced by something else with similar information, right? So, at your own risk... :-)

8:17 _na_ka_na_: chouser: thanks :)

8:21 ordnungswidrig: I'm playing with clojure agent. the tx spanning a dosync body will commit/rollback the state of all ref written, right?

8:22 raek: from outside the tx, all refs will seem to be untouched if the tx failed

8:23 i.e., all ref changes remains transaction-local until the transaction succeeds

8:23 ordnungswidrig: raek: and in the case (dosync (dosync (alter foo …) (alter bar …)) (alter foo bonk) when bonk fails, then bar remains altered?

8:24 raek: no, the outermost transaction gets restarted

8:24 ordnungswidrig: nice

8:24 raek: also, calls to send and send-off inside a transaction is held until it succeeds

8:24 ordnungswidrig: in what way can a tx fail? exception or validator, right?

8:25 raek: that or another transaction modified a ref that the current transaction relied on

8:25 in the latter case, the transaction is simply restarted

8:26 ordnungswidrig: in case of exception will the tx be rolled back and the exception bubbles?

8:27 raek: yes

8:27 ordnungswidrig: and in case of a validator?

8:27 raek: same thing

8:27 ordnungswidrig: exception?

8:27 clojurebot: http://paste.lisp.org/display/74305

8:28 raek: both will result in that no refs were changed, and that an exception comes out from the dosync block...

8:28 ordnungswidrig: raek: Ok, thanks for the tutoring :)

8:28 raek: np :)

8:29 ordnungswidrig: raek: to give you some context: I play with event-sources / cqrs using clojures stm.

8:29 s/event-sources/event-sourcing/

8:29 sexpbot: <ordnungswidrig> raek: to give you some context: I play with event-sourcing / cqrs using clojures stm.

8:31 raek: note that in clojure, you can have multiple threads banging on the same refs without concurrency problems

8:32 but thanks for the link. this looks interesting.

8:35 ordnungswidrig: interessting case with multiple threads. when doing command queueing / event sourcing you generally assume a serializable fixed order of events. thus you serizalize them at the outermost façade.

8:36 however when using a STM and CAS then you can also "listen" to the events acutally applied to the refs.

8:37 say, I don't care if the events were '(withdraw account1 200) (withdraw account2 100)' or vice-versa.

8:43 raek: I would be very interested in hearing about any findings you make in this STM + Event Souring area

8:43 ordnungswidrig: raek: any idea on how to capture the actual order of function application that where applied to refs?

8:44 raek: ordnungswidrig: well, there is add-watch

8:44 but then, you only get the value before and the value after

8:45 but if you store a [value event-causing-this-value] tuple in the ref, maybe it could be used anyway

8:47 (def a (ref [0 {:type :new-account}])) (defn withdraw [a x] (dosync (alter a (fn [[balance _]] [(dec balance) {:type :withdrawal, :amount x}]))))

8:48 ordnungswidrig: reak: i've seen the approach to attach the event as meta value onto the agent state and use add-watcher to extract the event out of the state.

8:49 raek: interesting

8:49 I don't have much experience with this, so this is all speculative ideas I have...

8:49 ordnungswidrig: but multiple agents mean multiple threads and I don't see where a "global" order of event can come from.

8:50 raek: you would need a master agent of some sort

8:50 ordnungswidrig: except the add-watchers sending the events to another agent "receiving" them

8:50 yes

8:50 on the watcher's side, right? not the "input" side.

8:51 raek: yes

8:51 is there any need for one global event sequence?

8:51 it could be constructed by merging the event sequences for all the refs

8:52 if transactions are used, changes that affect multiple refs will be safe

8:52 ordnungswidrig: but merge how? the events could depend on each other in theory.

8:52 raek: if you have, say, two accounts, each in one ref

8:53 ordnungswidrig: say that e2 on ref2 depends on a certain state of ref1 which was produced by earlier event e1

8:53 both in different threads.

8:53 the tx for e1 already was committed when e2 executed

8:53 raek: then e2 will be restarted with the new state

8:53 you can't change refs outside transactions

8:55 assuming that the change described by e2 is done in a transaction too...

8:56 chouser: don't forget about commute

8:57 cgrand: ordnungswidrig: you may also consider proxying refs you want to instrument, hence you will get access to the actual fn and args passed to commute or alter (disclaimer: half functioning brain here)

8:57 chouser: cgrand!

8:57 * chouser waves

8:57 cgrand: chouser!

8:58 angerman: I wish there was something like Ingredients for java ...

8:59 cgrand: what are Ingredients?

8:59 angerman: http://fileability.net/ingredients/

9:00 cgrand: thanks!

9:00 chouser: cgrand: which Guy Steele paper talked about keeping s-exprs as late in the macroexpand process as possible?

9:00 ordnungswidrig: yes, e2 sees the new state of e1. but the validator for e2 will check that a certain state of ref1 exists. e.g.

9:00 so e2 must be later executed after e1

9:02 cgrand: his thesis about RABBIT, and it was not only in the macroexpand phase in was in the whole compiler (macroexpansion, alpha rename, cps transform etc.)

9:02 chouser: ok, thanks

9:02 cgrand: yw

9:03 ordnungswidrig: chouser: do you have an example on commute? I understand the theory but I never saw how to use it.

9:05 chouser: ordnungswidrig: I mention it because it can allow for two transactions to touch the same ref at "the same time" without either restarting

9:06 I don't have a concrete use case for you. It turns I out don't use refs all that often.

9:10 raek: one example would be if two transactions tries to deposit money to the same bank account, commute would not cause the other transaction to restart.

9:10 if T1 adds money to the account before T2 is done, it doesn't matter for T2 in this case

9:12 ordnungswidrig: reak: but when you bank has no cash initially, then withdrawal on t2 might depend on deposit on t1 event when t1 was in a prio tx

9:15 raek: yes, you would not want to use commute for withdrawals

9:16 cummute is just like alter, except that the transaction does not restart if some else had changed that ref during the transaction

9:18 ordnungswidrig: so if I know the all functions applied on a ref are commuting then I can use commute instead, right

9:37 tonyl: good morning

9:42 angerman: is there a map that doesn't retain the head?

9:43 fliebel: Can anyone help me understand zippers? I get the up down left right stuff, but the same can't be said about modifying them. I want to add an item to the bottomrightmost branch.

9:44 I also don't understand the difference between a node and a loc.

9:45 tonyl: fliebel: I am starting to learn on zippers too, but I found a good quick explanation on how to edit them http://www.exampler.com/blog/2010/09/01/editing-trees-in-clojure-with-clojurezip/

9:45 fliebel: So I want to go from [1 2 3 [4 5 [6]]] to [1 2 3 [4 5 [6 7]]]

9:45 tonyl: I'll look at it.

9:46 chouser: fliebel: a node is one of the things you passed in orignially: a vector or number in your example

9:49 a loc is a zipper, that is a node plus its location in the whole tree

9:49 (-> [1 2 3 [4 5 [6]]] z/vector-zip z/down z/rightmost z/down z/rightmost z/down (z/insert-right 7) z/root)

9:50 cgrand: angerman: what do you mean?

9:50 angerman: cgrand: I guess I ment something like doseq or dotimes :D

9:51 chouser: the return value of each of those steps from vector-zip through insert-right is a loc. z/root walks from that final loc back to the root loc, and converts the root loc back into a node

9:51 fliebel: chouser: And what if I don't know the amount of nesting?

9:51 chouser: fliebel: you'll have to loop.

9:52 fliebel: chouser: With 'branch?'?

10:06 ordnungswidrig: does it make sense of have a ref holding a vector of refs?

10:07 opqdonut: probably not

10:07 chouser: ordnungswidrig: yes, but may be a premature optimization. Why not just a ref of a vector of values?

10:08 ordnungswidrig: chouser: i want different stm tx contexts for the contained refs.

10:08 chouser: and yes, it is premature optimization.

10:11 angerman: ,(float-array [[ 1 0 0]])

10:11 clojurebot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

10:11 angerman: hmm ..

10:12 mefesto: ,(float-array [1 0 0])

10:12 clojurebot: #<float[] [F@10a3ffc>

10:12 angerman: yea, it's 1d though :/

10:12 mefesto: ah

10:15 maybe this?

10:15 ,(into-array [(float-array [1 2 3]) (float-array [4 5 6])])

10:15 clojurebot: #<float[][] [[F@aaa10>

10:15 angerman: yea. looks like that. to-array-2d did return obj :)

10:16 mefesto: oh nice

10:19 fliebel: chouser: still stuck with zippers :( http://gist.github.com/645022

10:19 technomancy: http://p.hagelb.org/hammock.jpg

10:20 * mefesto hopes is boss allows for hammock time

10:20 mefesto: s/is/his/

10:34 jaley: hey guys! does anyone know if there's a function in core or contrib equivalent to this? ,(first (sort-by last (seq {:a 1 :b 2 :c 0})))

10:34 i find myself using it quite a lot :/

10:35 raek: I would write it without the seq call and with val instead of last

10:36 ordnungswidrig: am I correct, that the validator-fn of a ref reads the new values of any ref in the current ty?

10:36 s/ty/tx/

10:36 chouser: ,(apply max-key #(- (val %)) {:a 1 :b 2 :c 0})

10:36 clojurebot: [:c 0]

10:36 jaley: raek: yes.. that's more sensible

10:37 chouser: there is also a min-key

10:37 chouser: jaley: oh indeed, thanks.

10:37 ,(apply min-key val {:a 1 :b 2 :c 0})

10:37 clojurebot: [:c 0]

10:38 jaley: chouser: and thank you, because i hadn't found it either :p

10:38 Raynes: &(- 10)

10:38 sexpbot: ⟹ -10

10:39 ordnungswidrig: is the difference between refs and agents sync vs. async?

10:41 raek: ordnungswidrig: validators are used when the transaction body is finished and the changed refs are about to be written

10:42 ordnungswidrig: raek: so kind of last resort

10:42 raek: ordnungswidrig: yes, but agents are also uncoordinated

10:42 well, send operations are held in transactions..

10:43 ordnungswidrig: raek: in a agent validator-fn the values of other agents that are derefenced are coordinated?

10:44 raek: hrm, wait. validators could perhaps be checked at the alter calls. didn't think of that.

10:44 ordnungswidrig: only reads from refs are coordinated

10:45 and by coordinated I mean read from a single point in time

10:46 ordnungswidrig: hmm

10:49 ok, I think i've bean bitten by the uncoordinated part in agent :-)

10:50 when I reference a value of an agent in the update function of another agent, than there is no coordination, right?

10:50 theat means @(send a1 inc) will not necessarily return the new value

10:51 raek: exactly

10:52 agents don't guarantee that

10:52 the only thing you know is that the state transition function will be applied at some time in the future

10:53 ordnungswidrig: in my example in the update function I need to generade a globally unique id. managing that id with an agent would not work, but with a ref, yes, right?

10:53 raek: if you need rely on that the transition has been made, maybe agents aren't the best reference type to use in that sutuation

10:54 a ref would work, since it is synchronous

10:55 ordnungswidrig: assume each agent would containt the balance of an bank account, than there would be no way to ensure that the sum of balances of all account are positive, right?

10:59 * angerman doesn't get the BufferedImage Raster stuff...

11:00 angerman: image is always black (when painted using paintComponent) though the values in the Raster are not ...

11:01 raek: i.e., alter does not return until the transition has happened

11:01 ordnungswidrig: no. by the time you have checked all the accounts, they might have already changed. it sounds like a typical use case of refs... :)

11:01 "no" as in "there is no way"

11:02 Raynes: Refs are the only game in town for coordinated change.

11:03 raek: Raynes: back from the conj?

11:04 ordnungswidrig: but I should get multiple threads working on this if they work on mostly distinct sets of refs, right?

11:04 Raynes: raek: I was back yesterday.

11:04 I'm sick as hell.

11:05 raek: :(

11:05 Raynes: Blowing blood and such.

11:05 Guess I have a cold and a sinus infection.

11:05 Awaiting antibiotics.

11:07 raek: refs are safe to use in any number of threads combined with any number of refs. the performance might be bad if every thread alters every ref, though...

11:08 ordnungswidrig: also, have you seen this? http://blip.tv/file/812787

11:09 ordnungswidrig: raek: thanks for the pointer

11:09 Raynes: raek: If you've got the time, I'd be interested in hearing of the presents you've written me.

11:10 ordnungswidrig: raek: yes, if every tx reads every ref (like in the global balance example) then this cannot be parallelized

11:14 raek: Raynes: if course! :)

11:14 wait 10 minutes and I'll commit what I'm working on right now

11:15 just need to test it first

11:25 rdeshpande: howdy

11:27 ls

11:27 dfls

11:27 oops - sorry about that

11:27 tonyl: hehe

11:33 kevins: trying to get my clojure chops up but I'm having trouble getting my imperative head around this. This produces the first 1000 digit long fib number, but I need to know how many fibs came before it (i.e. some kind of counter while it's looping..how many calls to fibs were made?) I don't really know where to put something like a counter....Have a feeling I'm using the wrong approach.

11:33 (use 'clojure.contrib.lazy-seqs)

11:33 (take 1 (filter #(= (count (str %)) 1000) (fibs)))

11:34 chouser: kevins: how about take-while instead of filter?

11:36 KirinDave: kevins: I'd rewrite it to use keep-indexed.

11:37 florianjunker: aleph's websocket support is broken. In 0.1.0 it works, in 0.1.2 it doesn't.

11:38 * abrooks revels in the afterglow of clojure-conj

11:38 abrooks: I hope the videos are up soon. I keep wanting to link people to the various talks.

11:38 KirinDave: kevins: Something like this:

11:39 ,(take 5 (keep-indexed #(when (even? %2) [%1 %2]) (iterate inc 0)))

11:39 clojurebot: ([0 0] [2 2] [4 4] [6 6] [8 8])

11:39 KirinDave: kevins: (when ...) is your friend for keep and keep-indexed.

11:45 angerman: how would you write a histogram function in clojure? basically I have a sequence of all values. and now I'd need a value -> count mapping.

11:46 chouser: angerman: use, or refer to the source of, 'frequencies'

11:47 angerman: hmm let's see

11:48 mefesto: that should be in core as of 1.2

12:13 raek: how does this SNAPSHOT convention work? if I have "1.0.1-SNAPSHOT", is the next stable version "1.0.1" or "1.0.2"?

12:13 flx_: , (doc let)

12:13 clojurebot: "([bindings & body]); Evaluates the exprs in a lexical context in which the symbols in the binding-forms are bound to their respective init-exprs or parts therein."

12:14 cemerick: raek: the convention is that XXX-SNAPSHOT indicates unstable/development versions of XXX.

12:16 jweiss: if my macro just expands into a defn, i don't need to worry about using gensym on the args list right? because those symbols are only inside the scope of the defn anyway... right?

12:18 dpritchett: snapshot is a prerelease designation i believe

12:18 so it predates 1.0.1

12:19 also http://semver.org/

12:22 LLLLO: how would you go about stripping all mark-up from a html page

12:23 apgwoz: LLLLO: have a look at tagsoup (http://home.ccil.org/~cowan/XML/tagsoup/)

12:23 raek: LLLLO: I would use enlive and do a http://gist.github.com/645239 on the interesting node

12:23 LLLLO: also, envlive uses tagsoup for the parsing

12:24 apgwoz: LLLLO: what raek said, my next thing was to just pull out all the text nodes

12:24 LLLLO: hm

12:24 that single function does all that?

12:24 raek: an example of a titlebot that pulls out the title element http://github.com/raek/lcug-examples/raw/master/bot/src/se/raek/lcug/titlebot.clj

12:24 LLLLO: oh right, it requires to parse them into nodes first

12:24 what kind of nodes?

12:24 raek: however, it should use the function I posted before... currently it only takes the first text node

12:25 pdlogan: jweiss: if you are introducing new variables and splicing in a body of arbitrary expressions you need to ensure your new variables do not hide those in the body that should be "free"

12:25 raek: <foo bar="baz"><a/>quux</foo> --> {:tag :foo, :attrs {:bar "baz"}, :content ({:tag :a} "quux")}

12:26 LLLLO: tbh I first have to figure out where to put my downloaded clojure jars to be able to use them in REPL in clojurebox

12:26 pdlogan: OTOH if you are only creating new variables the programmer has explicitly designated as "new bindings" then you should be fine.

12:26 jweiss: pdlogan: ok like in a let inside the defn.

12:26 i think i should be fine there, thanks

12:26 raek: LLLLO: use a project management tool like Leiningen or Cake

12:27 LLLLO: will that work with slime?

12:27 ivey: LLLLO: "lein swank" starts a swank server inside the project

12:27 pdlogan: jweiss: e.g. (let [a 1 b 2] (jweiss-macro ... (+ a b) ...))

12:27 raek: yes, you run lein swank in the project and connect to it with slime-connect from emacs

12:28 LLLLO: http://github.com/technomancy/leiningen#readme

12:28 ivey: LLLLO: also, http://github.com/technomancy/durendal ... durendal-jack-in starts appropriate swank with lein, starts slime and connects it up

12:28 raek: oh, neat!

12:28 pdlogan: if jweiss-macro defines a or b in a new scope then "bad macro"

12:29 raek: LLLLO: look at the project.clj file of http://github.com/raek/lcug-examples/tree/master/bot/ for an example project.clj

12:29 pdlogan: it's always safe to gensym if you want "hidden" variables

12:29 jweiss: pdlogan: my generated code won't be needing to refer to anything outside its own scope

12:30 raek: the things you are interested in are probably the line containing enlive and swank-clojure

12:30 jweiss: well, ok some things, but i know the data passed to the macro will never collide with those things

12:30 LLLLO: man....

12:30 apgwoz: jweiss: "never" is an interesting word

12:30 LLLLO: back to make files and make command-line app, are we?

12:30 ivey: LLLLO: some of us never left...

12:30 LLLLO: I know

12:30 ivey: :-)

12:31 jweiss: well, the alternative is to have unreadable arg names on the fn my macro generates

12:31 raek: well, you do not have to worry about the CLASSPATH anymore

12:31 pdlogan: jweiss: if your macro includes the programmer's own expressions then there is a chance you could collide, that is all.

12:31 apgwoz: jweiss: the problem with macro expansion is the context that it's expanded in. that's how you get name capture.

12:31 raek: and with durendal, it seems that you don't even have to run the commands manually

12:31 apgwoz: if you can be sure that your macro only ever expands at the toplevel, then you're pretty much ok

12:31 jweiss: pdlogan: no expressions are passed to the macro

12:32 apgwoz: but, if your macro could be expanded within any other form, there's trouble

12:32 ... or at least potential trouble

12:32 raek: basically, Leinginen takes care of downloading the right jars and starting clojure with them on the classpath

12:32 jweiss: and i already know the context in which it should be expanded - all i'm doing is taking a data structure that defines an xmlrpc api, and defn'ing everything in there so that i have real clojure fn's instead of having to call the xmlrpc client explicitly every time.

12:34 LLLLO: hm

12:35 what does this do: (defn somefn [&rest] rest)

12:36 dpritchett: durendal-jack-in sure is taking its time for me, wonder if i can peek into it to see if it's working

12:36 i have a simple app going that i was using a manual lein swank + slime-connect process with before

12:36 is there a specific context i need to be in when i invoke durendal-jack-in?

12:36 ivey: dpritchett: it's a little slow for me too. it's starting swank, and i think it waits a while to make sure it's running fully

12:36 tonyl: LLLLO: [&rest] puts the rest of the arguments passed to the function in a vector

12:36 technomancy: it actually doesn't have to poll; it just waits for swank to announce it's listening on a port

12:37 but it has no error reporting, which is awful.

12:37 ivey: yeah whoever wrote it should be ashamed

12:37 LLLLO: tony1, it doesn't

12:37 dpritchett: so where do i invoke it from? I've got core.clj open in a window and i did a jack-in and my server is still "starting" 30s later

12:37 tonyl: ,(let [f (fn [& rest] rest)] (f :wer 4 5 3 "ewr"))

12:37 clojurebot: (:wer 4 5 3 "ewr")

12:37 LLLLO: if I run it with more than 1 argument it throws an exception

12:37 * technomancy glances around nervously

12:37 technomancy: LLLLO: needs a space between & and rest

12:38 tonyl: there should be a space between & and rest or whatever you want to name the sequence of arguments

12:38 * dpritchett browses durendal.el

12:38 tonyl: yup

12:38 LLLLO: right... but if there is no space, why does it return some weird object?

12:38 ,((fn [&rest] rest) "ha")

12:38 clojurebot: #<core$rest clojure.core$rest@e6529c>

12:39 LLLLO: wat?

12:39 clojurebot: For Jswat: start clojure with -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8888

12:39 LLLLO: lol

12:39 amalloy: ,(let [&rest 1] [rest &rest])

12:39 clojurebot: [#<core$rest clojure.core$rest@e6529c> 1]

12:39 technomancy: LLLLO: that's the value of the clojure.core/rest function, which is what the last thing in the fn resolves to

12:39 amalloy: LLLLO: ^^

12:39 tonyl: lol

12:39 LLLLO: ok makes sense now

12:41 dpritchett: yeesh, i mustve invoked it wrong. i can only find two durendal- functions available when i tab-complete from M-x

12:41 even though there are plenty more in the source

12:41 replaca: chouser: do you have any idea how to get my showoff preso onto heroku, but use your showoff rather than schacon's gem?

12:41 dpritchett: was (require 'durendal) at the bottom of init.el not enough?

12:41 technomancy: dpritchett: there's a distinction between interactive M-x commands and functions that only are called from elisp

12:42 dpritchett: ah

12:42 so putting (require 'durendal) \n (durendal-enable) on successive lines in init.el is good enougH/

12:42 or do i even need to run the enable command?

12:42 ivey: dpritchett: I don't run enable, and only call jack-in when I need it. It's the only piece I use so far.

12:44 dpritchett: thanks

12:46 LLLLO: "Closing over data is far more general than the simplistic model offered by private, protected, public, friend, et al. in OO languages." -> also 50 times slower

12:46 price to be paid

12:47 cemerick: LLLLO: why "50x slower"?

12:48 dpritchett: i did a quick `killall java` and and restarted emacs and durendal seems happy now. thanks for the tips

12:48 LLLLO: Don't know, but that's what my tests show

12:48 cemerick: LLLLO: I'm fairly confident your tests are wrong. :-)

12:48 LLLLO: creating closures means generating entire class :)

12:48 cemerick: only once, when the code is compiled

12:48 technomancy: 50 times slower to compile might be true, but the runtime cost is negligible.

12:49 LLLLO: no, since each closure is unique in regards to the data captured

12:49 it can't be created only once

12:49 cemerick: LLLLO: the bindings that are closed over changes every time you create one? Quite untrue.

12:50 LLLLO: ,(time (dotimes [n 100000] (Integer. n)))

12:50 clojurebot: "Elapsed time: 30.926 msecs"

12:50 technomancy: LLLLO: you're confusing creating a new class with creating a new instance.

12:51 LLLLO: still the times don't lie

12:51 dnolen: ,(time (dotimes [n 100000] (let [n (Integer. n)] (fn [] n))) )

12:51 clojurebot: "Elapsed time: 21.67 msecs"

12:52 LLLLO: yes now try to make the closure function like an object with 3 fields

12:52 cemerick: odd, that was faster than *not* using a closure ;-)

12:52 dnolen: LLLLO: but why you do that?

12:53 LLLLO: I don't know...maybe because it's given as an example in every clojure book?

12:53 as in, what you're supposed to do with the power of closures instead of using objects

12:53 dnolen: LLLLO: what books?

12:53 LLLLO: Clojure in Action for one

12:54 I'm pretty sure that Programming Clojure has the same thing

12:54 amalloy: LLLLO: closures are implemented as anonymous classes with an invoke() method. their constructor takes N arguments, one for each object it closes around

12:54 creating a closure is just a new X() - it's not slow

12:54 cemerick: LLLLO: I'd suggest pasting an example of these tests you've run, so this can get concrete.

12:54 dnolen: LLLLO: I'm pretty sure nothing of the kind is strongly recommended in Programming Clojure or Joy of Clojure

12:54 LLLLO: so not sure what you mean by "every book"

12:55 LLLLO: also several websites advocate this

12:55 http://www.nofluffjuststuff.com/blog/stuart_halloway/2009/08/rifle_oriented_programming_with_clojure

12:55 here's one

12:58 dpritchett: hey, durendal works better when you're running the latest clojure-mode

12:58 thanks for folding in the repl syntax highlighting technomancy

12:58 dnolen: LLLLO: Heh, yeah I wouldn't recommend that at all. using Closures to simulate mutable objects in Clojure is a terrible idea beyond understanding that it's possible.

12:58 LLLLO: strangely the difference is smaller here than on my work computer

12:59 what would you do instead?

12:59 dnolen: LLLLO: defrecord

12:59 LLLLO: (defn new-int [n]

12:59 (fn [comm] (cond

12:59 (= comm :value) n

12:59 (= comm :radix) 10)))

12:59 this for instance

12:59 (time (dotimes [n 100000] (new-int n)))

12:59 "Elapsed time: 13.852232 msecs"

12:59 (time (dotimes [n 100000] (Integer. n)))

12:59 "Elapsed time: 3.096241 msecs"

13:00 on my work computer it was 250 vs 4

13:00 or did I code that wrong?

13:00 Chousuke: you could probably use case for that

13:00 (case comm :value n :radix 10)

13:01 LLLLO: case?

13:01 Chousuke: (doc case)

13:01 amalloy: Chousuke: he's never calling the function; it doesn't matter what the function does

13:01 LLLLO: does it use java switch

13:01 Chousuke: hm

13:01 LLLLO: yeah I was just testing how fast the closure generation was

13:01 Chousuke: ah right. I didn't notice that.

13:01 LLLLO: if it's a bad idea

13:01 ,(doc case)

13:02 amalloy: LLLLO: if you're curious, try compiling to .class files and using javap -l (that's L)

13:03 it should show you exactly how much work it is to create a closure, and you can evaluate that yourself

13:03 LLLLO: hm

13:04 jarpiain: LLLLO: case compiles into a lookupswitch of the argument's hash code

13:04 amalloy: but there's no way it's 50 times slower. even if it closed around 50 variables (not sure that's possible) it shouldn't be 50 times slower

13:05 LLLLO: yeah that's weird then

13:05 but I'm pretty sure I had such results this morning

13:05 I am thinking about way I could have screwed it up

13:05 amalloy: dotimes is not a real benchmark. you get a lot of fluctuation due to, eg, whether your computer is busy syncing email

13:05 or whatever

13:06 dnolen: LLLLO: well we've been using Clojure for some time now and if the perf for closures was that bad we probably wouldn't be using Clojure ;)

13:06 amalloy: clojurebot: ping?

13:06 LLLLO: :D

13:06 hm gotta look-up the case macro on Clojure Docs

13:06 amalloy: he seems to be unstable more often now, for some reason

13:06 sexpbot: ping?

13:06 $ ping

13:06 sexpbot: amalloy: Ping completed in 0 seconds.

13:06 LLLLO: I have hard time reading (doc case), I don't understand the syntax

13:07 thank god for examples on Clojure Docs

13:07 ,(case first first true)

13:07 amalloy: LLLLO: clojurebot seems to be down. try sexpbot

13:08 ->(case first first true)

13:08 sexpbot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.MapEntry

13:08 LLLLO: what?

13:08 ->(case :first :first true)

13:08 sexpbot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to clojure.lang.MapEntry

13:09 LLLLO: ok this is weird

13:09 cemerick: jeez, are both bots hosed?

13:10 jarpiain: seems to be the bug I reported

13:10 http://www.assembla.com/spaces/clojure/tickets/438-case*-and-code-walkers

13:10 LLLLO: ->(+ 1 2)

13:10 sexpbot: ⟹ 3

13:10 amalloy: yeah, clojurebot is hosed, sexpbot doesn't get case statements, apparently

13:11 chouser: replaca: no -- let me know if you figure out a way

13:11 amalloy: LLLLO: your case statement works fine in a real repl

13:11 cemerick: why would it be doing any code-walking though?

13:11 LLLLO: oh ok

13:11 rhickey: anyone know what this is tryingto tell me? :

13:11 "/Users/rich/dev/clojure/build.xml:90: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds"

13:11 LLLLO: well the second one works, the first one doesnt

13:11 amalloy: LLLLO: that's because first isn't a compile-time constant, but :first is

13:11 chouser: replaca: I've moved all my "patches" except clojure syntax highlighting into the presentation itself, so that's the only thing missing when I push to heroku

13:12 cemerick: rhickey: you want to set includeantruntime="false" in your javac task usage (see http://www.jajakarta.org/ant/ant-1.6.1/docs/en/manual/CoreTasks/javac.html)

13:12 Or, *it* wants you to do that

13:13 rhickey: this message just started to appear after updating Java on my machine

13:13 i.e. build.xml hasn't changed

13:14 cemerick: rhickey: not sure what that indicates. I'm a long way from my ant days.

13:18 rhickey: This may or may not help. Did you upgrade your ant install too? http://ant.1045680.n5.nabble.com/warning-includeantruntime-was-not-set-td2639463.html

13:19 * rhickey didn't touch ant

13:40 amalloy: wow, i just stepped into ##java for a minute since i have to do some java for work. i now appreciate how friendly #clojure is

13:40 cemerick: yeah, it's a swamp over there

13:40 In their defense, they're pretty constantly bombarded by complete nonsense.

13:41 amalloy: yeah, i can imagine

13:51 zkim: amalloy: man you weren't kidding, just seen: "sproingie: then WHAT is your fucking QUESTION?"

13:51 amalloy: yeah, i can understand being fed up with that guy though

13:53 wow, his program is surprisingly close to being correct given how clueless he makes himself sound

13:54 zkim: hah

13:55 kumarshantanu: hi, is it possible to get a list of all vars in a namespace? e.g. clojure.core

13:55 zkim: kumarshantanu: http://clojuredocs.org/clojure_core/clojure.core/ns-map

13:55 cemerick: kumarshantanu: see ns-interns

13:58 kumarshantanu: zkim: cemerick: thanks

14:00 chouser: ,(dir clojure.set)

14:00 dpritchett: don't forget ##javascript - that place is scary

14:00 amalloy: chouser: clojurebot is down, sexpbot is working

14:01 dpritchett: *shudder* never will i ever. maybe i'll try #jquery if i have problems :P

14:02 dpritchett: i just discovered that clojure-mode had a new version when durandel.el invoked a nonexistent function - i googled it and wound up in clojure-mode.el. Is there a standard way to keep my elpa stuff up to date?

14:04 i would recommend #coffeescript if you want js help... just don't tell jashkenas i said so

14:05 amalloy: nah, if i ever need js help it'll be with jquery *chuckle*

14:05 zakwilson: paredit seems like a Good Thing in concept, but last time I tried using it, I found it difficult to get used to. Anyone here have opinions about whether it's worth it?

14:05 amalloy: zakwilson: everyone has opinions about it. they're not all the same

14:05 zakwilson: amalloy: that tends to be the way of things when it comes to opinions

14:06 amalloy: i find it convenient, but i've only been using it for a month or two and sometimes i get frustrated cause i can't remember the keystroke for X

14:06 mabes: zakwilson: I think it is well worth it. It being able to move parens easily, and promote forms is a real time saver IMO

14:07 amalloy: but i'm definitely in love with M-<up>, M-(, and C-<right>. they're the ones i use all the time

14:07 mabes: zakwilson: I'm by no means a power user either, I just use the basics.

14:07 * mabes nods

14:07 dpritchett: i would like paredit more if i knew basic emacs keyboard navigation I think... trying to figure out how to cut and paste something from outside of a sexp into said sexp was hard with no mouse

14:07 and i can't just move the parens manually

14:08 mabes: dpritchett: yeah, I've been using viper mode so I haven't even had to learn all the emacs bindings :) So far it has been pretty nice

14:08 amalloy: dpritchett: C-<right> is good if they're adjacent already

14:10 zakwilson: Conceptually, paredit and slime seem to move code editing away from *text* editing and in to a mode of interacting with the *meaning* of the code more directly. It just seems to be a bit of a learning curve.

14:10 dpritchett: i tried really hard to like viper but it had this 1 second lag on exiting insert mode that just drove me batty

14:10 i like to think i just set it up wrong.... vim's instantaneous mode switching is key to getting some editor flow going

14:11 it's hard to walk away from the turtles-all-the-way-down magic of elisp though :(

14:15 mrBliss: Is it true that finger trees "lookup items in O(n)"? http://david-mcneil.com/post/1393750407/clojure-conj-day-1-notes (search for "lookup")

14:16 chouser: mrBliss: looks like those notes got a few details mixed up.

14:17 double-list has amortized constant time for left and right ends, but the only access to the middle would be linear

14:17 * dpritchett digs into http://github.com/clojure/data.finger-tree

14:17 chouser: counted-double-list can look up by index in O(log(n))

14:17 zakwilson: I glanced through the PDF slides. It wasn't clear to me what finger trees are for.

14:18 mrBliss: what's the difference between the counted-double-list and the double-list (besides the faster look up times)?

14:19 chouser: :-(

14:20 mrBliss: that's pretty much it. counted-double-lists give you fast lookup by index

14:20 mrBliss: what's the trade-off?

14:21 amalloy: zakwilson: my understanding is that finger trees are a generalized functional data structure, which make it easy to implement other data structures as special cases of finger trees

14:21 chouser: oh, time during insert/remove and total meory

14:21 memory

14:22 mrBliss: chouser: thanks for the info. Do you have any idea when they'll be ready?

14:22 *finished

14:22 chouser: mrBliss: as soon as you've added the features you need.

14:22 :-D

14:24 zakwilson: I asked this before, but we have some different people around now. I'm doing a bunch of map lookups in a very inner loop. The maps are a few hundred to a few thousand entries, and the purpose of the lookups is to find the common keys between one and the rest. Keys are strings. What, if any speed optimizations might be possible?

14:24 mrBliss: chouser: I was planning to look into them as soon as they're finished ;-)

14:26 amalloy: chouser: what still needs work? i might be interested

14:27 chouser: zakwilson: off the top of my head, you might be able to get O(n) out of sorted-maps vs. what is probably O(n log(n))

14:27 amalloy: mostly just making sure they implement all the clojure.lang.PersistentCollection and java.util.Collection methods properly. I think mostly what's missing there are metadata, equality, hashing, that kind of thing.

14:28 amalloy: ah, cool. sounds like i might not even need to learn how they work to help, then :)

14:30 cemerick: g

14:30 defn: well hello everyone

14:31 apgwoz: hello defn

14:31 kumarshantanu: another question -- is it possible to defn a function like this -- (defn (quote (symbol "foo")) [] (println "foo")) ; getting error, but you know the intent

14:31 apgwoz: kumarshantanu: what's the use case?

14:32 kumarshantanu: trying to defn functions (root binding)

14:32 Raynes: kumarshantanu: Not without a macro.

14:32 Or eval, which is just bad juju.

14:32 kumarshantanu: any examples?

14:33 chouser: some options: macros, intern, alter-var-root

14:33 Raynes: Oh yeah, intern.

14:33 chouser: kumarshantanu: but a clearer description of your specific use case would be helpful

14:35 kumarshantanu: I am trying to build functions prefixed with "not-" for things like map? vector? empty? nil? etc

14:35 not-map? --> #(not (map? %))

14:35 chouser: (complement map?) ?

14:36 _na_ka_na_: hello. I'm trying to add a helper macro which takes a protocol and uses its :sigs to emit a deftype, only problem is that the protocol seems not to be available at macroexpand time .. if I put the macro body inside a function it works as expected

14:36 Raynes: When you find yourself doing stuff like that, remember the comp function as well.

14:36 (comp not map?)

14:36 mabes: also, for the opposite of empty? you should use seq

14:37 _na_ka_na_: kumarshantanu: in addition to what everyone has said .. we have if-not, when-not

14:37 cemerick: mabes: a contestable point :-)

14:37 kumarshantanu: I am trying to put them in the root so that they can be available in other namespaces -- is that a correct assumption (is it possible)?

14:38 I am asserting a lot...so "not" prefixed would be handy really

14:38 replaca: chouser: ahh, thanks. Maybe I'll just let web viewer miss out on that goodness. Are you going to push those syntax updates back to schacon?

14:39 _na_ka_na_: kumarshantanu: what do you mean by put them in the root?

14:39 kumarshantanu: root binding, I meant

14:39 chouser: if (complement map?) and (comp not map?) are too long, please consider writing your own 'complement' with a name you like rather than mucking about in clojure.core namespace

14:40 replaca: hm, I suppose I should.

14:41 _na_ka_na_: any ideas on how to write a helper macro which generates deftypes automatically given a protocol n some other args

14:42 another option is using a reify to directly give instances at runtime

14:43 inside a factory function

14:44 replaca: chouser: one more way to get Clojure on the map :)

14:45 amalloy: kumarshantanu: yeah, just this morning i was thinking it might be useful to (def ! complement), then you could eg (def not-map (! map?))

14:45 chouser: _na_ka_na_: you need a new class of some kind? you couldn't just generate arguments to a call to 'extend'?

14:45 _na_ka_na_: to give an example. (defprotocol P (foo...)) .. (helper-macro T [some params] P & some-args) => (deftype T [some params] P (foo ...))

14:46 kumarshantanu: amalloy: In fact I just want to write (not-map? x) instead of (not (map? x)) -- not-* is more readable

14:47 amalloy: kumarshantanu: that's exactly what my def lets you do...?

14:47 * zakwilson forgot that swap! at the slime REPL will print the new value and called it on an atom containing a 30,000 element map. Emacs kind of exploded.

14:47 amalloy: zakwilson: C-c C-c helps

14:47 kumarshantanu: intern seems to be doing it for me ---- (intern 'user 'foo (println "foo")) ; at the REPL

14:47 * chouser is sorry he mentioned intern

14:47 kumarshantanu: amalloy: yeah I need to defn some functions

14:48 amalloy: kumarshantanu: no, you don't need to defn. you can just def them with complement

14:48 kumarshantanu: chouser: I won't use it if you suggest so :)

14:48 _na_ka_na_: chouser: you mean (deftype T [some params]) .. (extend T P {:foo ..}) ?

14:48 chouser: kumarshantanu: please consider something like (! map?) or (not! map?) instead of generating vars

14:49 amalloy: (def not-map (complement map?)) is the same as (defn not-map [x] (not (map? x)))

14:49 kumarshantanu: amalloy: yes, right...def slipped my mind for a moment

14:50 _na_ka_na_: but I think kumar wants not- to be available in all nses like it was in clojure.core if I understand correctly

14:50 chouser: _na_ka_na_: yes. perhaps (apply extend (helper-fn T [some params] P & some-args))

14:50 Raynes: amalloy: Dude.

14:50 kumarshantanu: chouser: okay...I am fine with (defn not-map? [x] (not (map? x))) ; not-* looks more readable

14:50 zakwilson: chouser: quick and dirty test with sorted maps reveals it to be 25% slower that way.

14:51 amalloy: Raynes: yeah?

14:51 Raynes: amalloy: Couldn't you have left a "I didn't test this" note in your pull request somewhere? :p

14:51 chouser: zakwilson: you're walking both sorted maps in a O(n) way?

14:51 _na_ka_na_: chouser: yes that. extend is used at top-level like that ?

14:52 chouser: _na_ka_na_: yes, and is a function not a macro, so more composable and allows you to create things that are themselves more composable

14:52 amalloy: Raynes: sorry. left one last time; this time i either forgot or figured you'd remember i wasn't set up for testing

14:52 * chouser had a few things drilled into his head at the conj

14:52 Raynes: amalloy: :p

14:52 _na_ka_na_: chouser: thanks again!

14:53 amalloy: what's broken? i did test that it generated reasonable-looking strings

14:53 chouser: _na_ka_na_: if you actually need your function to genearte a new class on the fly, reify might useful. Not sure.

14:54 _na_ka_na_: chouser: yes both options have their place

14:55 amalloy: Raynes: um. okay that's kinda an embarrassing commit error. format-time needs another )

14:55 Raynes: Indeed.

14:55 ;)

14:55 zakwilson: chouser: I'm extracting the keys from one and looking it up in all the others using the functions intersection and difference, defined here: http://github.com/zakwilson/zutil-clj/blob/master/map.clj

14:56 So I guess what I'm really asking is: are these definitions of intersection and difference optimal?

14:56 amalloy: feel free to amend my commit so that it looks like i never sent that :P

14:57 chouser: I mean something like (let [o (reify)] (apply extend (class o) (helper-fn ...)))

14:59 jweiss: is there a recommended alternative to deliberately capturing a scoped variable in a macro? i want to generate a fn that closes over that variable

14:59 defn: chouser: finish reading lisp : the good parts yet? ;)

15:01 chouser: defn: no, but well on my way to converting to PDF to be loaded on my book-reading device of choice.

15:02 _na_ka_na_: chouser: how is that better than just (reify Proto ...) ?

15:02 * apgwoz is waiting for publishing company X to find someone to write Clojure: The Good Parts.

15:02 defn: nice :)

15:03 chouser: zakwilson: my point was that if you require the input maps be sorted by the same comparator, you could walk them both in step, generating your intersection in O(n) time

15:03 possibly more complex code, but the time cost would increase more slowly

15:04 _na_ka_na_: reify is a macro, so generating args to it has to happen at compile time forcing your helper to also be a macro and therefore get *its* args at compile time

15:05 _na_ka_na_: what I showed would allow your helper to be a fn and talk all it's input at runtime, as late as you'd like.

15:09 zakwilson: chouser: I may just be a little slow, but won't that fail comparing {"a" 1 "c" 3 "e " 5} with {"a" 1 "b" 2 "d" 4 "e" 5} (because it would either walk the whole thing or revert to a normal map lookup to see that "c" isn't there, and either walk until it finds "e" or revert to a normal map lookup)?

15:11 chouser: zakwilson: I may not be thinking about it deeply enough yet, but I do think you'd have to only advance the cursor that's farther behind.

15:15 zakwilson: chouser: I think you may be right and I may be thinking about things incorrectly. I will try writing it.

15:15 AWizzArd: chouser: which things were drilled into your head at the conj?

15:16 chouser: simple == "not compound", avoid macros, seek composable abstractions

15:16 there, now nobody has to regret missing it.

15:17 pbuckley: chouser: haha :-)

15:17 "the conj in 8 words"

15:18 but you left out hammock :-)

15:18 zakwilson: Are there videos from the conj?

15:18 chouser: pbuckley: that's a sub-point under "seek" :-)

15:18 pbuckley: zakwilson: they took video, but getting it edited and ready/posted might take some time

15:18 AWizzArd: chouser: what do you mean by “simple == "not compound"”?

15:19 zakwilson: pbuckley: that's to be expected.

15:19 chouser: AWizzArd: stuarthalloway asserted that "not compound" is the definition of "simple"

15:22 _na_ka_na_: chouser: but "not compound" is itself compound :P

15:22 chouser: heh. not a simple definition.

15:22 is there a function to get the comparator of a sorted thing?

15:23 AWizzArd: unfortunately not

15:23 Raynes: $dict simple

15:23 sexpbot: Raynes: adjective: Single; not complex; not infolded or entangled; uncombined; not compounded; not blended with something else; not complicated

15:23 AWizzArd: chouser: I wished FingerTrees would allow this.

15:24 chouser: AWizzArd: everything you customize a finger-tree with can be extracted later, I believe

15:28 alexyk: hey everybody! back in the virtual world, but it will never be the same again. I know what everybody else looks like and where he or she lives! Astonishingly, there were a few "she"s!

15:28 _na_ka_na_: chouser: continuing the reify talk .. assuming that let is at the top level, how do I extract the class to form more instances?

15:28 chouser: zakwilson: I have a sorted-intersection-with that seems to work. Should be O(n+m), worst case, but I haven't tested the performance at all.

15:28 mefesto: alexyk: great lightning talk! :)

15:28 alexyk: mefesto: thx!

15:28 chouser: _na_ka_na_: hm, you want more instances...

15:29 _na_ka_na_: chouser: for only one instance I could just create a helper factory fn containing reify ?

15:29 w/o extend

15:30 alexyk: chouser: in case you were left wondering, why I greeted your button with a promise to keep using cake, I have an explanation! :)

15:30 zakwilson: chouser: link/pastebin/etc?

15:30 chouser: _na_ka_na_: I'm trying not to recommend anything, just make you aware of options. I usually bad at doing the latter without doing the former.

15:30 zakwilson: you want it? Would hate to cheat you of the opportunity.

15:31 _na_ka_na_: if you want multiple instances of the same class, perhaps you could create the type first, then pass that class to a helper fn to generate the fns map that would be used by extend.

15:31 _na_ka_na_: chouser: in #clojure, its too late for you to not recommend anything, everything you say is "chouser branded" :P

15:31 chouser: in clojure irc, its too late for you to not recommend anything, everything you say is "chouser branded" :P

15:31 zakwilson: chouser: I have the algorithm in my head already, so I don't think I'd learn much by writing it myself. That aside, your code is probably prettier than mine, so I'll improve by reading it.

15:31 chouser: noooo

15:32 _na_ka_na_: your blog is full of things that blow me away. I really must refrain from coaching you!

15:33 apgwoz: chouser: i have a patch for contrib.command-line, what's the best way to submit it-- to you directly? pull request on github clojure/clojure-contrib project?

15:33 _na_ka_na_: chouser: that is exactly my plan :)

15:33 angerman: how would I transform keys in a hashmap?

15:34 _na_ka_na_: chouser: my blog?! I think you are mistaking me for someone else

15:34 replaca: apgwoz: put a bug on assembla with a patch

15:34 apgwoz: replaca: ok. cool

15:34 raek: angerman: (zipmap (map ... (keys m)) (vals m))

15:34 angerman: e.g. I have a fucntion scaler: key -> key that I want to apply to all keys

15:35 replaca: apgwoz: make sure you have a CA in and then follow the instructions here: http://clojure.org/patches

15:35 chouser: _na_ka_na_: ah, perhaps indeed. I was thinking of nakkaya.com.

15:36 zakwilson: http://gist.github.com/645575

15:37 apgwoz: replaca: I've signed the CA, though my membership to clojure-dev is still pending, thus I can't request assembla contributor role. though is that for naught anyway, given the eventual switch?

15:37 zakwilson: chouser: thanks

15:38 amalloy: clojurebot: ping?

15:40 replaca: apgwoz: good question. I would just put a bump request on the clojure-dev list. Stuart should give you rights. I don't think they've gotten to the actual issue migration yet.

15:40 * alexyk thinks he'd seen clojurebot at the conj, drinking Chivas near the bagpipes

15:40 apgwoz: replaca: i can't post to clojure-dev :)

15:41 regardless, thanks for the help

15:41 Raynes: alexyk: That was sexpbot.

15:42 clojurebot was passed out behind the stage.

15:42 alexyk: Raynes: aha! BTW, I missed meeting hiredman. :( What did you look like, hiredman?

15:42 replaca: hmm, you should be able to request that too. :)

15:42 alexyk: Raynes: clojurebot misinterpreted the sex in sexpbot

15:42 apgwoz: replaca: i did, a couple of weeks ago. never got processed apparently

15:42 Raynes: alexyk: Like David Liebke with uglier facial hair.

15:43 ;)

15:43 alexyk: Raynes: fewer of those?

15:43 replaca: hmmm...

15:43 Raynes: He was standing in front of me talking to danlarkin and friends.

15:43 alexyk: Raynes: yeah, as if I could remember who stood there! I got an extra white ticket for that!

15:43 danlarkin: frienddddddddds!!!!!!

15:43 chouser: apgwoz: it's best to get some input on a patch too, before submitting. I'm no longer reading all g.group messages, but posting there is always good

15:44 alexyk: quoting Raynes, you guys are my best fwends <3

15:44 apgwoz: chouser: yeah, i will certainly do that once I get access.

15:44 angerman: how would I go about writing a "peak"/"valley" detector on a histogram?

15:44 apgwoz: chouser: for some reason I was thinking /patches applied only to clojure core, which of course is wrong. :)

15:44 chouser: apgwoz: just the regular clojure g.group is fine. Here, all I'll add a thing that flags me if the message contains "chouser"

15:45 alexyk: angerman: partition by two, replace by the sign of the difference

15:45 angerman: I assume i could move a window with take/drop along the keys of the histogram and check if (max vals ...) == val for key, but that sounds somewhat stupid.

15:45 raek: apgwoz: is there an issue for the bug/enhancement? if not, you can create one while only being a watcher...

15:45 angerman: alexyk: it needs to be a bit more robust.

15:45 alexyk: the data is not very smooth :(

15:45 alexyk: angerman: partition by the function > or <

15:46 with a threshold

15:46 ie > by 3

15:46 apgwoz: raek: oh. under support. interesting.

15:46 raek: i was looking only in "tickets" which doesn't have a "new ticket" button anywhere.

15:47 raek: also, if you create an account, make sure to use a username that is your real name

15:48 alexyk: angerman: http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/partition-by

15:49 danlarkin: angerman sounds like hiredman's alternate personality

15:49 chouser: cemerick: I can probably help with contrib build gruntwork, but I'm in no position to lead or make decisions there. Strikes me as right up your alley :-)

15:49 angerman: alexyk: that sounds like a good idea I'm still wondering how I'd keep it local. e.g. make sure to only have a window of +-10 datapoints.

15:49 danlarkin: sorry to disappoint you :p

15:49 alexyk: danlarkin: angerman is a fired hiredman!

15:49 oh, that's disgruntledman

15:51 defn: heh

15:51 homicidalman

15:51 alexyk: hey defn! you've made it out of the clutches of RDU!

15:51 defn: just barely! :)

15:52 yet another late night on Saturday. Just got into work at 2:30pm

15:52 alexyk: defn: ALl American Food almost detained me too

15:52 defn: haha -- luckily i had chouser to keep me awake while I waited to board

15:52 alexyk: before that, that guy Hohn from DC poured us all on the shuttle some godo whisly from a bottle. Now that's hwo conferences are done.

15:52 John

15:53 who knows John from DC? what's his nick? that guy is my hero now

15:53 he was there with Alex, they are from some government contractor or other; or Maryland, perhaps

15:54 next time, gotta take a flask to the conj, I'll get those cgrand's slides the instant I see them!

15:54 _fogus_: alexyk: I know him.

15:54 alexyk: _fogus_: cool! does he have a Twitter?

15:54 _fogus_: good dude

15:54 defn: back to work

15:55 ill be around later, ciao

15:55 alexyk: defn: later

15:55 pbuckley: alexyk: I don't know his nick on IRC, but he's @sirlyric on twitter

15:55 alexyk: pbuckley: ah ok, saw him there

15:55 pbuckley: don't you find NH weather a letdown after NC?

15:56 pbuckley: alexyk: yeah a bit colder - it was warmer outside at night in NC that it is inside my house

15:56 _fogus_: that's the one! Was trying hard to remember his twitter id. People should avoid handles for my convenience. :p

15:56 alexyk: pbuckley: I flew through Philly and it was 70 there. Just rain here. But programming is so much better in the rain!

15:57 _fogus_: at least we learned you really don't have horns!

15:57 angerman: hmm. adding to the tail of a list is just not easy :(

15:57 alexyk: angerman: keep adding to the front, then revert the result :)

15:58 angerman: yea.

15:58 chouser: ok, putting "chouser" in a message to the clojure user's g.group should be more visible to me now than others. Recommended for anyone wanting me to take a patch for something. :-)

15:58 raek: angerman: you can append to the back of a vector, then run seq on it

15:59 ,(loop [x 10, acc []] (if (zero? x) (seq acc) (recur (dec x) (conj acc x))))

16:00 ->(loop [x 10, acc []] (if (zero? x) (seq acc) (recur (dec x) (conj acc x))))

16:00 sexpbot: ⟹ (10 9 8 7 6 5 4 3 2 1)

16:00 tonyl: ->(range 10 1 -1)

16:00 sexpbot: ⟹ (10 9 8 7 6 5 4 3 2)

16:00 tonyl: ->(range 10 0 -1)

16:00 sexpbot: ⟹ (10 9 8 7 6 5 4 3 2 1)

16:01 angerman: damn i ran out of mem ... now emacs hangs

16:03 chaslemley: hey guys, recently started using clojure solving euler problems and wanted to write something more non-trivial so I worked on this over the weekend, for parsing a haml type html template: https://gist.github.com/2964d548027eb63c19d7

16:04 based on a ruby gem a friend of mine has built

16:04 i was just wondering if there's any use for something like this to interface with compojure or if it's overkill, already been done, etc

16:08 pbuckley: chaslemley: I don't know the answers to your questions, but I think it's a cool idea.

16:09 alexyk: _fogus_: just found out you interviewed Odersky! Are you a secret Scalaist? :)

16:09 chaslemley: cool, thanks

16:10 _fogus_: alexyk: I wouldn't say secret no.

16:10 alexyk: _fogus_: man, you even got Harrop there! awesome

16:11 apgwoz: chouser: you should perhaps get your first message tagged chouser in a second or two

16:11 _fogus_: alexyk: I don't know who that is... but he keeps coming back to comment.

16:11 alexyk: _fogus_: if you don't know who Jon Harrop is, you don't know Haskell or F# :)

16:11 lrenn: or comp.lang.lsip

16:11 AWizzArd: stuart wrote in the GG “code path for using vars is now *much* faster for the common case” — what is meant by “code path”?

16:11 raek: Is there any fuzz testing lib for clojure?

16:12 AWizzArd: regarding 1.3 Alpha 2

16:12 alexyk: _fogus_: and you might as well keep it that way for your peace of mind :)

16:12 _fogus_: alexyk: I guess I need to read more about Haskell then.

16:12 alexyk: he'll be surpsrised by your mildmannered replies :)

16:13 _fogus_: he is the bane of Haskell and Lisp! And apparently Scala too

16:14 _fogus_: alexyk: Oh... I think I see now.

16:14 chouser: apgwoz: It worked. :-) I'll take a look, but I'm beginning to think the design of contrib.command-line is too ...um... compound.

16:14 it shouldn't require a patch to add validation

16:18 apgwoz: chouser: yes, it is a bit difficult.

16:18 and not that friendly.

16:18 i do like the simplistic format of the spec though.

16:19 raek: I'm a bit puzzled regarding how to solve "the error problem". I have a function that parses a string into a map. not all strings are syntactically valid. what should the parse function do when it encounters an invalid string.

16:19 Raynes: _fogus_: The only thing you need to know about Jon Harrop is that HASKELL SUCKS F# AWESOME YAY!1!!1!

16:19 raek: my options seems to be: 1. pre/post-conditions 2. returning nil 3. throwing some exception

16:20 or maybe 4. calling *syntax-error*, which the user would have to rebind

16:20 _fogus_: Raynes: So you're saying I should abandon learning Haskell? ;-)

16:21 Raynes: In his humble opinion YES AND EVERYTHING ELSE LEARN F# YAY!1!!1!

16:21 chouser: raek: sounds about right.

16:21 raek: so, dear #clojure. how do you do error reporting?

16:21 * KirinDave listens eagerly as well

16:22 alexyk: raek: (throw (Exception. "arrgh!"))

16:22 chouser: raek: you could bind *syntax-error* to a fn that throws an exception, then call it in your parser and do something useful with the return value

16:23 rdeshpande: well, i can't really speak for how to do this in clojure, but i would typically return some sort of symbol that corresponds to a key in a translation file (maybe a yaml) that has the readable, localized error message

16:23 chouser: this would default to Java-style expection-throwing, but allow a sufficiently concerned user to control the behavior and avoid losing the rest of the parsing if they so desired.

16:30 raek: chouser: thanks for the suggestions. :) the binding + fallback to exception way does have a clojurey feel to it, i think...

16:32 also, the defdynamic thingy is in Clojure 1.3.x, right?

16:33 chouser: raek: ^:dynamic, but yes 1.3 alpha 2

16:33 raek: for the exception to throw by default, consider clojure.contrib.condition. It may not be worth the dep, but might be worth considering.

16:35 zakwilson: chouser: I couldn't plug your sorted-intersection-with directly in to my code, but I tried it with some extracted data. It's about 10x slower.

16:35 chouser: heh. nice.

16:36 nickik: man do i wait for the videos don't really get all that new stuff

16:37 danlarkin: contrib.condition is nice

16:37 * TeXnomancy concurs

16:38 * alexyk laments that so many cool nicks remained undevirtualized

16:38 chouser: have you guys added your features to contrib yet, or still keeping them to yourselves?

16:38 contrib.condition features, I mean.

16:39 danlarkin: I think we have a patch up on assembla?

16:39 Oh, or maybe Steve already committed them

16:40 cemerick: chouser: Thanks. I sorta did a facepalm as I read Stu's initial email. Any expertise I have in that alley is much to my chagrin, really. :-)

16:41 chouser: cemerick: yeah, I know.

16:41 but there it is

16:41 technomancy: build conscription. =)

16:41 chouser: maybe you can talk the other stu into it instead

16:42 cemerick: chouser: after his drawn-out battle over the modularization of old-world contrib, I couldn't in good conscience ask him to lead it.

16:42 technomancy: watch it, I may start throwing feature requests at you ;-)

16:43 * technomancy glances around nervously

16:43 chouser: technomancy: or you! I'd be happy to be required to use your One True Build Tool in exchange for having someone sanely manage contrib builds.

16:44 technomancy: is this from a specific mailing list thread or just general "how are we going to do this" discussion?

16:44 chouser: I already wrote my own pom.xml for finger trees because I thought it was what was required. I'll clearly go to any length, if only they'll tell me what to do.

16:44 amalloy: chouser: One True Build System? it looked like you were struggling to find an OTBS there

16:45 technomancy: if it's just a matter of getting hudson to deploy locally to build.clojure.org I can help

16:45 I don't know the first thing about archiva/nexus though

16:46 cemerick: The local-install-to-repo thing is decidedly not the right thing to do.

16:48 kevins: is there way to stop the repl without killing it? (i.e. runaway function). This is especially bad in netbeans/enclojure where I currently have to stop the entire IDE.

16:49 cemerick: kevins: No. This will improve to some extent as more people adopt nrepl, which supports evaluation interrupts.

16:49 technomancy: maybe once a nexus is set up I could help getting some of the projects pointed at it

16:49 kevins: thanks.

16:57 amalloy: do we have an iterate-while construct? i often find myself wanting (take-while f (iterate g x))

17:01 apgwoz: cemerick: with nrepl, has anyone discussed porting SLIME to use it, or creating a new mode for use with it?

17:01 (obviously in emacs)

17:02 technomancy: apgwoz: it will probably happen eventually

17:03 nobody has volunteered yet. =)

17:03 apgwoz: technomancy: i think it might be beyond my elisp skills...

17:03 though, maybe not... i don't know :)

17:04 rata_: hi

17:04 arbscht: apgwoz: the other way seems easier: write a clojure-side adapter like swank-clojure but for nrepl

17:05 chouser: kevins, cemerick: see 'clojure.contrib.repl-utils/add-break-thread!' to make Ctrl-C interrupt runaway tasks in the current thread.

17:05 apgwoz: arbscht: i suppose interpretting the swank protocol would be easier

17:06 though, that sort of bastardizes nrepl, don't you think?

17:07 chouser: ok, finger-tree slides are up at http://talk-finger-tree.heroku.com/ in a format that doesn't require downloading a giant PDF.

17:07 apgwoz: otherwise, nREPL should just implement SWANK and be done.

17:07 cemerick: chouser: There's no way to send a Ctrl-C in enclojure or ccw, AFAIK

17:07 apgwoz: chouser: oooh, smooth transitions!

17:07 chouser: cemerick: oh, sure.

17:08 Raynes: Isn't there something in Clojure to get the line separator for the system you're on?

17:08 * Raynes thinks he remembers something, but not sure what

17:08 chouser: cemerick: those who live by fancy tools may sometimes die by them. :-)

17:08 amalloy: (System/getProperty "line.separator") as i recall

17:08 Raynes: I know the Java way, but I thought I remembered something in Clojure itself.

17:08 I might be mistaken.

17:09 muhdik_: is clojure any good?

17:09 Raynes: It's all sorts of good!

17:09 mabes: muhdik_: this group might be biased ;)

17:09 apgwoz: Raynes: (def line-seperator #(System/getProperty "line.separator")) ? :)

17:09 amalloy: muhdik_: nah. we just like hanging out here...

17:09 arbscht: apgwoz: implementing swank isn't the easiest thing to do; the protocol is unstable, and often assumes a CL runtime (or at least a CL reader). it'd be wise to isolate swank-fu in a module like an adapter than to build nrepl around it

17:09 muhdik_: u can make anything that you can with java in clojure i mean?

17:09 Raynes: apgwoz: Read above.

17:10 apgwoz: Raynes: i know, my comment was in response to your "I know the java way"

17:10 .. and was a joke :)

17:10 Raynes: Oh. I'm too ill to get jokes.

17:10 muhdik_: or not?

17:10 chouser: muhdik_: pretty much anything worth making, anyway. :-)

17:10 apgwoz: Raynes: oh, sorry you're ill :(

17:10 amalloy: muhdik_: yes, you have access to everything java has, if you need it

17:10 Raynes: $wiki turing completeness

17:10 sexpbot: First out of 1040 results is: Turing completeness - Wikipedia, the free encyclopedia

17:10 http://en.wikipedia.org/wiki/Turing_completeness

17:10 muhdik_: oh so u can make webpages?

17:10 apgwoz: arbscht: right, swank is complicated, which is why I'm asking why it makes sense to bastardize nREPL with a SWANK interpreter

17:11 muhdik_: i mean ecommerce

17:11 apgwoz: arbscht: well, a SWANK to nREPL interpreter of course

17:11 muhdik_: is it?

17:11 hmmm

17:11 arbscht: apgwoz: for SLIME compatibility. SLIME has the same problem as swank, only on a larger scale. it seems to me that it makes less sense to reimplement a SLIME-like than a swank adapter

17:12 raek: muhdik_: there are web frameworks, so yes

17:12 muhdik_: i mean does oracle own clojure?

17:12 apgwoz: arbscht: while it's more work, it probably does make sense, given that you no longer have to make special cases. nREPL is to clojure as SLIME/SWANK would be for CL.

17:12 muhdik_: or just java

17:12 because oracle doesnt have a clue

17:13 raek: oracle does not own clojure, rich hickey and the contributors do

17:13 apgwoz: arbscht: no one is saying the nREPL mode wouldn't be influenced (heavily) by SLIME...

17:13 muhdik_: ok cool

17:13 arbscht: apgwoz: well, nrepl is to clojure what swank is to CL. there's no SLIME-like in nrepl. but if it makes sense to you to build one, go ahead, I'd use it. :)

17:13 muhdik_: is clojure the same as f# in the .net world?

17:14 raek: I would say that F# and Scala are more similar

17:14 zakwilson: muhdik_: I think Scala is more limilar

17:14 similar

17:14 muhdik_: clojure is like linq then?

17:14 chouser: the .net equivalent of Clojure is ClojureCLR

17:14 apgwoz: arbscht: right. at some point in time, i might be willing to attempt to take on that project... but unfortunately not now.

17:14 muhdik_: ok

17:16 apgwoz: arbscht: of course in my previous statement with the analogy, it should have been nREPL-mode/nREPL for maximum correctness.

17:16 arbscht: apgwoz: I understand

17:17 apgwoz: arbscht: ok. just clarifying :)

17:17 cemerick: chouser: sure, sometimes; though, you can s/fancy/"simple" there, too. ;-)

17:18 chouser: so true

17:18 * cemerick invokes "simple", expects halloway to come in here and smite me.

17:18 chouser: which reduces to something like "no tool is perfect". go figure.

17:19 jweiss: i'm trying to call apache xmlrpcclient that has 2 overloads for .execute: String,Object... and String,List. i am passing in a clojure vector so i thought it'd hit the latter, but seems to be hitting the former. type hinting as java.util.List didn't help. any suggestion?

17:20 chouser: ->(instance? java.util.List [])

17:20 sexpbot: java.lang.NullPointerException

17:20 fhd: Hi

17:21 Is there something like reify that I can use to extend classes?

17:21 reify and deftype do apparently only work with interfaces

17:22 replaca: fhd: You have to use gen-class

17:22 chouser: fhd: proxy

17:22 jweiss: chouser: not sure what the result of that sexpbot experiment should tell me

17:22 replaca: chouser: does proxy support extending?

17:23 chouser: replaca: yessir

17:23 fhd: chouser: Cool, I'll try that :)

17:23 replaca: Hah, of course! That's what I use in pprint :)

17:23 chouser: jweiss: yeah, me either. :-P Maybe you'd better paste your code somewhere. hinting to List should do it

17:23 replaca: you taught me two years ago, but I haven't done it since

17:26 jweiss: chouser: http://gist.github.com/645803

17:27 oops i typo'd List->list but i had it right before and still didn't work

17:27 fhd: chouser: Works, thanks :) A bit confusing though that there is deftype, proxy, reify (and I guess a few others)

17:27 chouser: replaca: :-)

17:29 fhd: yeah. and worse that the proxy syntax is rather different

17:30 fhd: By the way, can I watch the clojureconj talks online?

17:30 Raynes: How would one pprint a map with newlines inserted in the appropriate places? The default is to print it all on one line with commas separating key -> value pairs.

17:30 fhd: I heard rumours they'd be recorded

17:30 technomancy: fhd: it'll be a few weeks at least

17:30 petrilli: fhd - hopefully. I'd like to watch them again, even though I was there.

17:30 fhd: technomancy: Damn, I was really looking forward to this :(

17:31 petrilli: Also, I'd like a replay of Rich talking about pods at the BBQ... so I can listen to it 50 times to understand it hopefully.

17:32 fhd: Then again, it takes weeks until the talks are uploaded for most conferences I follow

17:32 technomancy: petrilli: well the emerginglangs talk will cover that

17:32 fhd: Don't really know why, is the world of video recording that unrestrainable?

17:32 dnolen: Raynes: pprint is useful for that.

17:32 petrilli: technomancy: awesome... I thought I got it, then had another beer, went ot sleep and woke up confused.

17:32 Raynes: dnolen: Indeed, I'm asking how one would use pprint to do the above.

17:33 dnolen: The docs are kind of a brick wall.

17:33 technomancy: I'm disappointed that I never got to meet you at the Conj. I just admired you from a distance. <3

17:34 petrilli: I'm still trying to figure out if he types standing up.

17:34 pjstadig: he does

17:34 petrilli: Wow... I thought I was hardcore with a desk that raises up so I can type standing up, but I still use a Model M

17:35 chouser: fhd: & args would make args a seq not a vector

17:36 hm, but that should still implement java.util.List.

17:37 drewr: petrilli: I almost pulled out my phone to record it

17:39 technomancy: Model Ms are the best, modulo RSI concerns. if I could get a split one I would be all over it.

17:40 petrilli: technomancy: Email Unicomp... I did. They own all the patents, and also all the tooling to build it. If they knew they could sell enough, I'm sure they would.

17:40 * technomancy raises an eyebrow

17:40 fhd: K, gotta run. cya!

17:41 petrilli: technomancy: sales@pckeyboard.com

17:42 * nDuff hugs his Filco

17:43 technomancy: Raynes: it was all a blur; so much going on.

17:43 nDuff: http://elitekeyboards.com/products.php?sub=filco_keyboards,majestouch_104key

17:44 jackdempsey: funny, i was reading about this today

17:44 my msoft natural elite 4000 is still the only piece of msoft shit i use

17:44 petrilli: For me, nothing will ever trump the buckling spring keys in the IBM and Unicomp keyboards.... I type 30-40% faster. And thanks to Clojure, I've not worn out the shift key yet

17:45 nDuff: petrilli, these also use real mechanical switches; they are indeed a thing of beauty.

17:46 petrilli: nDuff: Cool. I'd need to check one out... if I ever wear this one out... my original, circa 1990 Model M still works

17:47 Now I just need to find somewhere that doesn't think saying that "we have a fully integrated SOA architecture" is actually useful.

17:49 apgwoz: when using clojure.contrib.socket-server, is there a way to get details (i.e. for logging) such as the client's ip address?

17:54 from within the the handler that is.

17:58 ... it certainly doesn't look like it via the source, but someone might have a thought on the matter? is it a doomed thought?

18:00 lazy1: apgwoz: The server object has :connections, my guess you can use that somehow

18:02 apgwoz: lazy1: there's no guarantee that the last conjed element is for the thread that just started.

18:02 so, while it'd potentially work, it'd be buggy

18:02 jweiss: so if a java method take varargs and i want to create a clojure method that calls it with however many args are in a list (NOT the list itself, that's just one arg), what do i do? there's no apply for java methods. and i can't use macro because i need to evaluate the form that creates the list

18:03 sorry create clojure fn

18:03 apgwoz: jweiss: supply an array as the last argument. a java array

18:03 jweiss: apgwoz: yeah i tried that, somehow the lib i'm calling doesn't like it

18:04 lazy1: apgwoz: You're right, however there might be something in the connection object you can use (maybe compare input-streams). But my guess it's a dead end

18:04 * lazy1 waiting for someone to prove me wrong ...

18:04 apgwoz: lazy1: yeah, we're already getting hacky when we start comparing input streams :)

18:05 lazy1: apgwoz: Switch to aleph? (maybe, not sure if it will give you what you need)

18:06 apgwoz: lazy1: yeah, i don't want async, which is why server-socket is perfect. if only the functions in server_socket.clj weren't private, then i'd write a new create-server.

18:07 privacy is a double edged sword.

18:09 I think I'm write here, defn- functions can't be exported at all outside of the namespace they were defined in right? It's not just left out of the default namespace, correct?

18:09 (by default namespace, i mean, the default exports, like you'd get when you (use 'lib))

18:12 lazy1: apgwoz: IMO the shortest path is to copy the code and change accept-fn to pass the socket object as well)

18:13 apgwoz: lazy1: yeah, I agree. it's certainly not ideal though.

18:30 AWizzArd: http://java.sun.com/docs/white/langenv/Simple.doc2.html <-- I love point 2.2.4 :-)

18:32 “Object oriented programming supersedes functional […] style.”

18:33 plathrop: How do I write java code that runs as a daemon?

18:33 Adamant: now I know why I hate Java so much

18:33 plathrop: s/java/clojure/

18:33 sexpbot: <plathrop> How do I write clojure code that runs as a daemon?

18:34 plathrop: I've seen lein-daemon, but I'm not sure that's right for running on a production box

18:34 nDuff: plathrop, ...use a process supervision tool to run your arbitrary foreground process in the background!

18:34 plathrop: nDuff: That's an option I'd prefer to avoid. I'm an Ops guy who has bitched incessantly about devs who do that :-P

18:35 nDuff: plathrop, I'm an ops guy and I _hate_ developers who write things to only be usable as daemons.

18:35 plathrop, daemontools or runit gives you status monitoring, automatic restarts, a consistent control interface...

18:36 plathrop, ...ability to run triggering events on shutdown or prior to restart (ie. automated cleanup)

18:36 plathrop: Whereas I like things that fit in to the OS properly and run as real daemons. I like the *option* to run in foreground, but I want the program to be able to be a daemon too

18:36 nDuff: plathrop, ...ability to record the signal that caused your exit or the exit status...

18:37 plathrop: All valid points

18:37 nDuff: plathrop, "real daemons" are an anachronism, and modern operating systems are moving away from them; look at the movement towards Upstart.

18:39 plathrop: And who watches your watchdog daemon?

18:39 nDuff: plathrop, my watchdog daemon either _is_ my init (PID 1) process, or is directly supervised by it.

18:43 plathrop: I guess I'll look at wrapping apache-commmons daemon for my purposes. Thanks

18:53 LLLLO: ll

18:58 f

19:03 !time

19:03 !time

19:04 !time

19:09 !time

19:09 TheAnimal: LLLLO: 26.10.2010 01:10:23 +0200

19:13 amalloy: damn. someone tell that boy to use a test channel

19:18 ->(take 2 [1])

19:18 sexpbot: ⟹ (1)

19:20 KirinDave: Sometimes it's the best feeling in the world to use gen-class

19:20 amalloy: ->(->>[nil nil 1 nil nil] (drop-while nil?) (take 2) (keep identity))

19:20 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: (#'clojure.core/keep)

19:20 amalloy: ,(->>[nil nil 1 nil nil] (drop-while nil?) (take 2) (keep identity))

19:20 KirinDave: And be like, "Dear other jvm languages, you can suck what I am giving you. If you don't want to get slapped around, I suggest you enjoy it."

19:21 amalloy: argh both of the bots hate me

19:21 ,(->>[nil nil 1 nil nil] (drop-while nil?) (take 2) (filter identity))

19:21 ->(->>[nil nil 1 nil nil] (drop-while nil?) (take 2) (filter identity))

19:21 sexpbot: ⟹ (1)

19:22 hsuh: was clojureconj recorded?

19:22 jackdempsey: hsuh: evidently yes, and videos potentially in weeks or more

19:25 plathrop: How do you implement signal handling in clojure?

19:25 KirinDave: plathrop: Like, UNIX signal handling?

19:25 plathrop: nDuff: So, if you are using a watchdog process, how do you make it so the watchdog process can nicely stop your service?

19:26 KirinDave: yeah. I have clojure I want to run as a daemon. If I run it under upstart it will be sent a TERM segnal

19:26 I need to make sure I clean up and exit nicely

19:26 KirinDave: plathrop: Ha.

19:26 plathrop: Find someone who's done that work over the jni.

19:26 That's the only realw ay

19:27 plathrop: oh dear

19:27 Nobody is running clojure as unix daemons then?

19:27 nDuff: plathrop, it depends; runit _does_ allow you to override event handlers, so you can provide a command to be run in place of a SIGTERM

19:27 plathrop, ...and that command can use whatever your preferred polite-shutdown-method may be.

19:28 plathrop: nDuff: how can that command access the internals of the service though?

19:28 KirinDave: plathrop: As much as they are java.

19:29 plathrop: There are still a lot of green pastures.

19:29 arohner: plathrop: check out lein-daemon

19:30 nDuff: plathrop, that's your implementation decision. Tomcat uses a command socket; I'm trying to remember the standard-ish approach that we used two jobs ago, but it's escaping me without some (ongoing) googling.

19:30 plathrop: arohner: yeah, I'm looking at it. thanks

19:31 nDuff: ahh -- it was a JMX command-line tool

19:31 ...that we had our control scripts invoking.

19:32 plathrop: nDuff: oh, okay. that seems like adding a lot of complexity just for the luxury of not using an init script? I'm not trying to be a dick I'm really trying to understand the right way to do this.

19:32 (I say since I've already been flamed to a crisp elsewhere for trying to figure out why you'd want to use a watchdog program)

19:33 nDuff: plathrop, *shrug*. At that time, I was sysops staff, _not_ java dev staff. Using JMX shifted a lot of pain from the ops team onto the java team.

19:34 plathrop, ...maintaining a separate init script for every distro which happens to interpret the LSB's standards for how they should behave a little bit differently is Really Not Fun, by the way.

19:35 well, not that much pain, as the Java folks were already supporting JMX anyhow

19:35 so it was really saving labor all 'round

19:36 plathrop: huh. okay

19:36 At this point this is sounding like way more of a project than I bargained for for something as simple as I'm working on

21:04 amalloy: argh i hate mutable state. please let me work in clojure instead of java

21:10 rata_: amalloy, I sympathize with you. mutable state is hateable

21:30 TeXnomancy: mmm... new lein plugin task uses juxt

21:30 thank you trptcolin, wherever you may be.

21:30 and ivey =)

21:30 it's a little-known fact that I can't reject a patch that includes a call to juxt.

21:30 ivey: heh

21:31 that's all trtpcolin. I just merged the thing.

21:31 However, that's good to know about juxt...

21:31 * ivey starts thinking of ridiculous lein patches featuring juxt

21:34 amalloy: ,(((juxt juxt juxt) juxt juxt) juxt juxt juxt juxt)

21:34 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (4) passed to: PersistentVector

21:34 amalloy: aww what

21:34 ivey: ->(buffalo buffalo buffalo buffalo)

21:34 sexpbot: java.lang.Exception: Unable to resolve symbol: buffalo in this context

21:34 amalloy: ,((juxt juxt juxt) juxt juxt juxt juxt)

21:34 clojurebot: [#<core$juxt$fn__3665 clojure.core$juxt$fn__3665@4218cb> #<core$juxt$fn__3665 clojure.core$juxt$fn__3665@169c6f2>]

21:35 TeXnomancy: ~o/

21:35 clojurebot: \o ... High five!

21:35 amalloy: ,(apply ((juxt juxt juxt) juxt juxt) juxt juxt juxt juxt)

21:35 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$juxt

21:35 amalloy: bah, i give up

21:35 but i love the high five

21:36 TeXnomancy: ((malkovich malkovich malkovich) malkovich malkovich)

21:37 trptcolin: oh wow, sorry for apparently indirectly starting this :) (just got caught up on the juxt conversation)

21:38 ivey: trptcolin: buffalo

21:38 trptcolin: doh!

21:39 rata_: ,(((juxt juxt juxt) juxt juxt) [juxt juxt] [juxt juxt])

21:39 clojurebot: java.lang.IllegalArgumentException: Wrong number of args (2) passed to: PersistentVector

21:43 TeXnomancy: trptcolin: I think this subtask-help mechanism could be abstracted and shared

21:43 trptcolin: TeXnomancy: absolutely

21:43 TeXnomancy: I know autodoc needs a similar thing

21:44 trptcolin: there's also other stuff in lein-plugin that was essentially copied from another task (install, i think) that i was planning to simplify once we get merged

21:45 interesting, i hadn't thought of it being abstracted into its own thing outside of leiningen, but that makes sense

21:49 TeXnomancy: I'm thinking having subtask support in the help namespace actually

21:49 maybe subtasks could be metadata on a task, and help could check it.

21:50 trptcolin: ah, gotcha. i was just looking at autodoc for the first time - didn't realize it was already depending on leiningen anyway

21:52 sounds pretty clean to me

21:52 TeXnomancy: dare I say simple? =)

21:53 trptcolin: oh noez!!! ;)

21:54 TeXnomancy: pushed

21:55 Nafai: Were there videos taken of the conference?

21:56 TeXnomancy: Nafai: yes, but not professionally.

21:56 the Conjure guy brought recording gear

22:05 drewr: Nafai: no guarantee on when they'd be up

22:05 * Nafai nods

22:05 trptcolin: technomancy: cool, just pushed a typo fix. i'll tackle moving the help stuff over, as well as adding some tests for that & plugin stuff. probably not tonight though

22:06 Nafai: I'm actually wanting to see Rich's keynote

22:06 trptcolin: so if you want to grab it first that's cool

22:09 technomancy: hah; nice catch. I was debugging and left that out.

22:09 no rush on the help moving.

22:11 trptcolin: cool.

22:12 Nafai: the keynote was great! 5-word summary: "Think hard. Write it down."

22:12 Nafai: Yeah, sounds inspiring

22:12 Raynes: Don't forget hammock time.

22:15 trptcolin: :) yeah +1 to technomancy for the "stop. hammock time" image

22:15 technomancy: http://p.hagelb.org/hammock.jpg

22:15 trptcolin: technomancy: how many people did you get asking about the google venn diagram today?

22:15 amalloy: haha, that's great

22:16 trptcolin: and as a follow-up, did you know there was another technomancy before that?

22:17 technomancy: trptcolin: I saw that on hacker news; the guy behind technomancy.org

22:22 jweiss: anyone got some real-life examples of error-kit use? the example in error-kit.clj is a little too simple. i can't figure out if the caller can specify his own handlers or not, and if so, do they have to be named in the with-handler form, or can they be external?

22:26 rata_: what's the name of the function that returns [(filter pred coll) (remove pred coll)]?

22:26 I'm almost sure there is one

22:29 jackdempsey: lol

22:29 hammock time. nice.

22:30 trptcolin: ,(clojure.contrib.seq-utils/separate even? (range 10))

22:30 clojurebot: [(0 2 4 6 8) (1 3 5 7 9)]

22:32 rata_: thanks trptcolin

22:32 trptcolin: sure

22:38 technomancy: separate needs to be reimplemented using juxt

22:38 it's a textbook juxt

22:39 (juxt (comp filter pred) (comp remove pred))

22:43 trptcolin: i was juxt looking at that

22:46 actually, i really was looking at it for another reason - takes 2 traversals. could be just 1 with less elegant code

22:47 technomancy: reduce!

22:48 it's like juxt, but less indie.

22:49 lancepantz: group-by solves the same problem, i'm not sure how its performance characteristics are relative to juxt though

22:50 trptcolin: looks pretty fast to me.

22:50 ,(vals (group-by even? (range 10)))

22:50 clojurebot: ([0 2 4 6 8] [1 3 5 7 9])

22:51 trptcolin: and it uses transient so you know it's fresh

22:52 lancepantz: i find myself doing group-by + destructing quite a bit

22:59 defn: Stop. Hammock time.

22:59 trptcolin: indeed. peace out

22:59 defn: night tr

23:01 howdy monsieur lancepantz

23:02 technomancy: can I quote you on juxt and it being less "indie"

23:02 technomancy: well, it's reduce that's no longer indie

23:03 but I used to listen to reduce before it was on the major labels.

23:03 (for the record)

23:03 defn: hahahaha

23:03 that's /awesome/

23:03 btw, great image -- i had a similiar idea which ill need to sleep on ;)

23:04 waking mind is preventing me from commiting to it

23:06 rata_: good night :)

23:07 see you tomorrow

23:11 lancepantz: hey defn

23:11 how was the flight back?

23:11 have to ride the bus again?

23:12 defn: not too shabby -- only trouble was i crossed my right leg over my left and promptly fell asleep. feels like i have a staph infection in my right leg as a result.

23:12 going home was easy compared to the 1:30am bus ride on the way down

23:13 lancepantz: i bet

23:13 defn: still tired from the 3 nights of consecutive "stay up until 3am talking code, go to bed, wake up at 7am and go to talks for 12 hours" routine

23:14 but i had a mini breakthrough at work on clojure -- sounds like people are starting to get more and more interested

23:15 lancepantz: yeah i missed the morning talks the second day

23:15 hung over from the night before

23:18 defn: i made it and wanted to kill myself most of the afternoon

23:18 rich's talk owned, though...

23:18 lancepantz: yeah, i loved it

23:19 defn: some people were being sort of snarky about it which sort of pisses me off

23:19 lancepantz: really?

23:19 oh, how was the bbq btw?

23:20 defn: awesome. i broke a corona on stu's floor and made his foyer smell like beer for what i would imagine is the foreseeable future

23:21 *facepalm*

23:21 i think i apologized 2-400 times, cleaned it up, vacuumed, begged forgiveness, etc.

23:22 lancepantz: hehe

23:23 defn: but anyway, the {:bbq "fantastic"}

23:23 chapel hill is beautiful area

23:25 lancepantz: how was your trip home

23:26 lancepantz: long and sleepily

23:26 i can't sleep on planes

23:27 for that matter, i couldn't sleep at the conj either

23:27 so i slept til 2pm on sunday

23:27 didn't get to go surfing, disappointed

23:27 needed the sleep though

23:41 amalloy: ooc what was the mean age at the conj? am i talking to surprisingly hip old geezers, or surprisingly mature young'uns?

23:42 (or is it rude to even ask on irc? not exactly an irc veteran myself)

23:43 maravillas: seemed like a decent mix to me

23:45 defn: in my view: the people who were young are destined to be the people who were older

23:45 amalloy: haha i like that

23:46 defn: i had a guy who was in his 50s ask me my age and then tell me he was using emacs before i was born

23:46 my only response was that someday ill be in a similar position

23:46 amalloy: defn: you'll still be using emacs when he's dead!

23:47 * defn chuckles

23:47 defn: he was a nice guy -- we're all the same, hunting for a better solution to our problems

23:47 amalloy: yeah

23:47 defn: anyway, age is irrelevant, i talked to people who were 5 years my junior who put my knowledge to shame

23:47 amalloy: well yeah. i mean, Raynes was there

23:48 defn: (inc Raynes)

23:49 speaking of which, we need to have karma added to sexpbot. it used to be nick++, but should be implmeneted in sexpbot as (inc nick)

23:50 im gonna go read some lisp in small pieces for awhile

23:50 cheers

23:50 amalloy: AS IT HAPPENS i'm in the middle of adding bits to sexpbot

23:50 defn: amalloy: nice.

23:50 amalloy: but i don't know how karma's supposed to work :P

23:50 defn: it's simple. (inc nick) gives nick +1

23:50 {:nick 1}

23:51 (inc nick) => {:nick 2}

23:51 (dec nick) => {:nick 1}

23:51 anyway, gotta get a bit of reading in before bed, ciao

Logging service provided by n01se.net