#clojure log - Sep 15 2010

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

2:56 LauJensen: Good morning all ya'll

2:58 defn: morning

2:59 amalloy: mornin'

2:59 bobo_: yo!

2:59 im boored at my php at work, cant it be conj-labs soon!

3:02 LauJensen: Unfortunately no - Im really looking forward to this one as well

3:12 amalloy: neat, i hadn't heard of conj-labs yet. Laujensen: http://www.conj-labs.eu/instructors.html misspells career

3:12 LauJensen: Thanks! :)

3:13 fixed

3:13 amalloy: If you want to tag along, talk to your boss asap, we're almost sold out

3:14 amalloy: nah, never gonna happen. <shameless-plug>www.hubpages.com</shameless-plug> is gonna be on PHP forever

3:15 bobo_: amalloy: i code php at my current assignment aswell...

3:15 LauJensen: amalloy: You should criticise your company so heavily in public like that

3:15 s/should/shouldnt/

3:15 sexpbot: <LauJensen> amalloy: You shouldnt criticise your company so heavily in public like that

3:15 amalloy: hah

3:17 benefits/speed uses parallize instead of parallelize

3:18 LauJensen: fixed, thanks

3:19 amalloy: next time the tech industry crashes i'll moonlight as a copy-editor

3:19 course/practical: s/breakfeast/breakfast

3:22 anyway lj, it sounds neat. let me know when you're in california :)

3:22 LauJensen: I'll be sure to do that :)

3:23 I just had a connection reset, so if you said anything after I said 'fixed, thanks' it got lost

3:23 amalloy: (12:16:54 AM) amalloy: next time the tech industry crashes i'll moonlight as a copy-editor

3:23 (12:17:46 AM) amalloy: course/practical: s/breakfeast/breakfast

3:23 defn: lau, you a cake user?

3:23 LauJensen: defn: yes sir

3:23 amalloy: (and now i've read the whole thing. no more typos from me)

3:23 LauJensen: amalloy: even if it is a feast? :)

3:24 amalloy: thanks for your feedback, big help

3:24 defn: LauJensen: how's it going for you?

3:24 amalloy: i doubt the hotels provide real feasts, even in germany

3:24 LauJensen: defn: Really well

3:24 defn: LauJensen: yeah I'm super impressed

3:25 LauJensen: Me too- I love their task system

3:25 defn: the persistent JVM can sometimes be a little annoying

3:25 amalloy: as someone who's satisfied with lein, what does cake do that i should be interested in?

3:25 LauJensen: yes, and it has a bug

3:25 defn: but it's a small price to pay for a persistent JVM

3:25 it's beautiful sometimes

3:25 LauJensen: amalloy: a persistent JVM (ie. no startup time after the first command), a great dependency based task system and its truely cross-platform, easy to install on Windows

3:25 defn: LauJensen: oh? which bug is that?

3:26 LauJensen: defn: Sometimes commands that follow each other in a short space of time can generate a BindAddress Exception, they're looking at it now though

3:26 defn: amalloy: it also lets you do up front default configuration so you can create new projects with default :dependencies and :dev-dependencies

3:26 LauJensen: amalloy: And also, its a drop in replace for lein

3:26 defn: yeah they're basically compatible

3:26 amalloy: hmm. persistent jvm sounds nice, but i'm blessed to use ubuntu at home and at work

3:27 defn: amalloy: im not sure i understand?

3:27 amalloy: ie, don't care much about the cross-platform stuff

3:27 defn: ubuntu has some sort of default persistent JVM or something?

3:27 LauJensen: amalloy: hehe, PHP and Ubuntu, you're giving me strange images in my head. But how does that relate to cake?

3:27 defn: amalloy: im not sure how cross-platform means anything for cake

3:27 LauJensen: amalloy: ah ok. One day you might get a customer who requires building to take place on a Windows server. Thats my situation right now and Cake solved it

3:27 defn: cake runs on *nix and OSX

3:28 LauJensen: defn: read what I said above about x-platform

3:28 defn: amalloy: do you have autotest built in?

3:29 amalloy: ummmmm, i might, but since i've never heard of it chances are slim

3:29 defn: i dunno, cake does a lot more than that

3:29 it's pretty awesome -- worth a look

3:30 Lupus79: what are you using tasks for?

3:30 err LauJensen

3:30 LauJensen: defn: I have a build which needs to compile an embedded database, download a bunch of things from the net depending on some specs given in a config folder and then put all of that into an executable jar

3:30 amalloy: defn: believe it or not, searching for "clojure auto test" yields a lot of results :P. what am i actually looking for?

3:30 LauJensen: ...on Windows

3:30 defn: LauJensen: pepijn and i are working on a static site generator with cake tasks

3:31 amalloy: it's a way to continuously run your tests against your existing code

3:31 when you save a file it notices, and runs your tests against the new code

3:31 you have a scrolling window of tests -- you write one that fails, then you write the code to satisfy the test, repeatr

3:31 repeat*

3:32 the window shows you when you've met the requirement

3:32 http://en.wikipedia.org/wiki/Continuous_integration

3:32 read that before i get a case of the clojurian fantods

3:34 amalloy: defn: after i'm done reading about the etymology of fantods

3:36 LauJensen: defn: Didn't know Cake already had support for autotest

3:41 defn: amalloy: :)

3:42 LauJensen: it's great.

3:42 People have balked at the Ruby/Clojure marriage in Cake but I think it's really superficial -- the tool seems to do what I'm interested in doing.

3:43 LauJensen: Sure, and Ruby is a huge plus for me. Its a relatively small bootstrap that lets me be completely x-platform

3:43 If you have a problem with that, you should have a bigger problem with the bash/lein relationship

3:58 amalloy: if anyone has some spare brain time, i've put a description of a problem i need to work out an algorithm for at www.malloys.org/~akm/canonical.txt. i'd love some suggestions to prevent me going too deep down a silly road before i get started

4:13 LauJensen: amalloy: first tip: dont solve this using PHP, second tip: dont make me scroll all the way to the right to read the end of every line...please :)

4:14 amalloy: LauJensen: heh, sorry. i'm surprised browsers don't wrap .txt files. and yes, this is for my clojure project

4:16 LauJensen: added hard line breaks if you refresh

4:21 jjido: since the values are sorted, each box contains a series of adjacent segments. I would intersect the whole box segment (lowest to highest) with other boxes, then look closer at those that have non-empty intersection

4:24 amalloy: jjido: hmm. interesting idea. the boxes will tend to be pretty small, so i'm not sure how much this buys me but it's worth thinking about

4:32 jjido: how do I implement a fork-join kind of parallel algorithm? Agents?

4:34 grignaak: jjido: there used to be a wrapper around fork-join. but this page says its deprecated http://clojure.org/other_libraries

5:50 fliebel: Is there a better way than this to put together a line-seq? (apply str (interleave seq-of-lines (repeat \newline)))

5:52 (and what was the the name of the fn that did nothing at all?)

5:53 ordnungswidrig: I have an problem where my algorithm must iterate a list multiple times and I wonder if I can enhance it.

5:54 kumarshantanu: ordnungswidrig: share a gist maybe?

5:55 ordnungswidrig: basically for every split of the list [s1 s2 s3 s4 …],i.e. [] [s1 … s4], [s1] [s2…s4], [s1,s2] [s3,s4]….

5:55 I have to check the left partition and the right partition. but the check of the right partition need the reverse iteration of the right part

5:57 Currently i have the steps: iterate over the list and split into a partition, say [p1 p2 p3.. pn] [a1 a2 a3…an]. Second iterator over the ps to calculate sth. then reverse iterator over the as to calc sth else.

5:58 Chousuke: fliebel: identity

5:59 fliebel: Chousuke: Nice name...

5:59 ordnungswidrig: so that are three iteration and the calculation over the ps and as can be done iteratively, e.g. as reduction and are the same for each partition. i.e. (calc p1 p2 p3) always gives the same result and can be calculated from (calc p1 p2) and p3

6:01 so that there are three iterations....

6:02 kumarshantanu: ordnungswidrig: probably a pastebin.com or gist.github.com entry will help undrstand it better

6:03 ordnungswidrig: kumarshantanu: I have no code at the moment but I will gist it soon

6:03 kumarshantanu: a little confusing, what I wrote. :-)

6:04 kumarshantanu: ordnungswidrig: yeah I can't get the picture readily from the description

6:05 ordnungswidrig: kumarshantanu: i wouldn't either

6:06 is there a way to get all partitions [[] [x1..xn]] [[x1] [x2..xn]] [[x1 x2] [x3..xn]] [[x1 x2 x3] [x4..xn]] .. [[x1..xn] []] for the list [x1..xn]?

6:09 ,(let [l (range 1 10)] (map #(take % l) (range (count l))))

6:09 clojurebot: (() (1) (1 2) (1 2 3) (1 2 3 4) (1 2 3 4 5) (1 2 3 4 5 6) (1 2 3 4 5 6 7) (1 2 3 4 5 6 7 8))

6:12 Chousuke: -> (for [i (range (count [1 2 3 4]))] ((juxt take drop) i [1 2 3 4]))

6:12 sexpbot: => ([() (1 2 3 4)] [(1) (2 3 4)] [(1 2) (3 4)] [(1 2 3) (4)])

6:13 ordnungswidrig: I don't like the count

6:13 Chousuke: -> (for [i (range (inc (count [1 2 3 4])))] ((juxt take drop) i [1 2 3 4]))

6:13 sexpbot: => ([() (1 2 3 4)] [(1) (2 3 4)] [(1 2) (3 4)] [(1 2 3) (4)] [(1 2 3 4) ()])

6:14 Chousuke: -> (take 5 (for [i (range)] ((juxt take drop) i [1 2 3 4]))); I guess you can do this too

6:14 sexpbot: => ([() (1 2 3 4)] [(1) (2 3 4)] [(1 2) (3 4)] [(1 2 3) (4)] [(1 2 3 4) ()])

6:14 ordnungswidrig: ,(reductions conj [1 2 3 4 5])

6:14 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IPersistentCollection

6:14 Chousuke: but note that the seq will be infinite

6:15 ordnungswidrig: ,(reductions conj [] (range 1 5))

6:15 clojurebot: ([] [1] [1 2] [1 2 3] [1 2 3 4])

6:19 ordnungswidrig: ,(let [l (range 1 5)] (map (fn [i] [(take i l) (drop i l)]) (range (count l))))

6:19 clojurebot: ([() (1 2 3 4)] [(1) (2 3 4)] [(1 2) (3 4)] [(1 2 3) (4)])

6:32 kjeldahl: ,(if (= 1 9) (println "abc") (do ((println "def")(println "ghi")nil)))

6:32 clojurebot: java.lang.NullPointerException

6:32 kjeldahl: Anybody feel like clueing me in?

6:33 LauJensen: ,(if (= 1 9) (println "abc") (do (println "def")(println "ghi")nil))

6:33 clojurebot: def ghi

6:33 LauJensen: thats your clue :)

6:33 kjeldahl: Thanks!

6:35 ordnungswidrig: kumarshantanu: http://gist.github.com/580531

6:36 ,((print 1))

6:36 clojurebot: java.lang.NullPointerException

6:37 bobo_: ,("asdf")

6:37 clojurebot: java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn

6:37 ordnungswidrig: ,(nil)

6:37 clojurebot: java.lang.IllegalArgumentException: Can't call nil

6:37 LauJensen: ,(:hey)

6:37 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :hey

6:37 ordnungswidrig: ,(print 1)

6:37 clojurebot: 1

6:37 ordnungswidrig: why then the NPE on ,((print 1))

6:37 bobo_: what does print return? nil?

6:37 ordnungswidrig: ,(1)

6:37 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

6:38 LauJensen: ,(nil? (print "hi"))

6:38 clojurebot: true

6:38 hi

6:38 ordnungswidrig: bobo_: yes, print returns nil but clojurebot seems to mess this up

6:38 why would return print it args?

6:39 bobo_: why does (nil) and ((print "asdf")) return different errors then?

6:40 LauJensen: bobo_: nil is a special case

6:40 bobo_: so its different to call nil and something that retuns nil?

6:41 ordnungswidrig: ,(letfn [(px [rest] (do (print rest) rest))] (px (+ (px 1) (px 2))))

6:41 clojurebot: 3

6:41 123

6:41 ordnungswidrig: ,(do (print 1) 2)

6:42 clojurebot: 2

6:42 1

6:42 ordnungswidrig: weird, why does ,(print 1) omit nil then?

6:42 LauJensen: bobo_: yes

6:42 I think nil is implemented as a cornercase

6:43 ordnungswidrig: LauJensen: so (nil) -> IllegalArgumentException (let [x nil] x) -> NPE?

6:44 LauJensen: ,(((constantly nil)))

6:44 clojurebot: java.lang.NullPointerException

6:44 LauJensen: ,(nil)

6:44 clojurebot: java.lang.IllegalArgumentException: Can't call nil

6:45 ordnungswidrig: I hope for 2.0 there is better error reporting on the replease plan :)

6:47 LauJensen: I think when the Compiler is called with nil, it just rejects. When its called with a body its parses it one item at a time, hence the different exception, its in a nested try/catch around here: http://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L5369

6:57 What am I missing here

6:57 ,(let [b (Boolean. "false")] (println (class false) \: (class b) \: (not false) \: (not b)))

6:57 clojurebot: java.lang.Boolean : java.lang.Boolean : true : false

7:07 LauJensen: ,(let [b (Boolean. "false")] (println (false? b) \: (true? b)))

7:07 clojurebot: false : false

7:16 raek: I can't understand why they didn't make that constructor private...

7:17 LauJensen: my bad. Its a known (and document?) design decision for performance concerns

7:17 Use Boolean/FALSE or read-string if you need to parse input

7:17 raek: ,(Boolean/parseBoolean "false")

7:17 clojurebot: false

7:18 raek: ,(let [b (Boolean/parseBoolean "false")] (println (false? b) \: (true? b)))

7:18 clojurebot: true : false

7:21 kjeldahl: ,(for [scvec [1 2 3]] (println scvec))

7:21 clojurebot: (nil nil nil)

7:21 kjeldahl: ,(for [scvec [1 2 3]] (scvec))

7:21 clojurebot: java.lang.ClassCastException: java.lang.Integer cannot be cast to clojure.lang.IFn

7:21 Chousuke: what are you trying to do?

7:22 kjeldahl: It's wierd. In my repl environment, that line works (the first one). I get output. When I run the same code as part of some other code, the code inside the for loop doesn't seem to execute.

7:23 (and no, the code doesn't just output stuff, that's just for verification)

7:25 LauJensen: kjeldahl: for is lazy, are you evaluating it ?

7:25 ,(let [b (for [i (range 5)] (print i))] nil)

7:25 clojurebot: nil

7:25 LauJensen: ,(let [b (doall (for [i (range 5)] (print i)))] nil)

7:25 clojurebot: 01234

7:26 kjeldahl: I have no idea what you're talking about, but it sounds correct.

7:26 LauJensen: kjeldahl: A lazy sequence is not evaluated until you consume its elements. Its only a promise of evaluation

7:26 consider

7:26 ,(take 5 (iterate inc 0))

7:26 clojurebot: (0 1 2 3 4)

7:27 LauJensen: if (iterate inc 0) wasn't lazy, it would compute towards infinity

7:27 (take 5) evaluates 5 (actually more but thats a detail) elements

7:27 fliebel: LauJensen: Because of chunking?

7:27 LauJensen: fliebel: (actually more) = chunking

7:31 kjeldahl: So what's the simplest way to iterate over all elements in a vector then, not lazily?

7:32 spariev: ,(doseq [i [1 2 3]] (print i))

7:32 clojurebot: 123

7:33 LauJensen: kjeldahl: for, map, filter etc are for non-side-effectfull operations, ie functional programming. dotimes and doseq are for side-effects. It depends on what you want to do

7:34 kjeldahl: Excellent. doseq was what I needed. Thanks all.

7:53 LauJensen: Whats the ideal way to mimic an html table representation in Swing ?

7:56 maravillas: miglayout feels a bit like html tables, if you squint

7:56 bobo_: jtable?

7:57 LauJensen: bobo_: JTable would be fine, except its a hassle to implement buttons and dropdowns in it, so its more a visual thing. maravillas Im already using miglayout as the layoutmanager

7:57 fliebel: LauJensen: The default layout is kind of like a 3x3 table… not what you want probably. My Swing is to rusty.

7:58 LauJensen: although these guys seem to be loving it http://www.jasperpotts.com/blog/2007/09/nimbus-almost-done/

7:58 but then again, the java sharks seem to be okay with writing a few thousand lines of code per component

7:59 bobo_: yeh, swing is... not fun in any way

7:59 LauJensen: true

8:00 bobo_: http://blogs.sun.com/geertjan/entry/simple_example_for_an_outlineview i liked that example, its not pure swing but still

8:00 it is supposed to show how easy it is. i think it shows how increadibly much code it requires for hardly anything

8:01 fliebel: LauJensen: If you're a Python guy, you might try writing ugly interfaces with the Java tcl bindings :P

8:01 LauJensen: fliebel: You might want to check out some of my older posts on the blog :)

8:02 fliebel: LauJensen: How old? Where's your search box?

8:02 LauJensen: ,google python vs clojure

8:02 clojurebot: java.lang.Exception: Unable to resolve symbol: google in this context

8:03 LauJensen: clojurebot: google python vs clojure

8:03 clojurebot: First, out of 32100 results is:

8:03 Best In Class: Python vs Clojure - Evolving

8:03 http://www.bestinclass.dk/index.php/2009/10/python-vs-clojure-evolving/

8:03 bobo_: oh, i missed your best in class tour post

8:03 LauJensen: I did two of them. I come off as though I hate Python which I dont, its actually on my top 5 list of languages :)

8:03 bobo_: :(

8:03 bobo_: i blame my vacation!

8:04 LauJensen: bobo_: You can hook up an RSS reader to get notified when something happens, either that or keep up with me on twitter

8:04 fliebel: LauJensen: What are the other 3?

8:04 bobo_: i think you are in my rss, and on twitter. i must have failed somehow

8:05 LauJensen: fliebel: Clojure, Haskell, Python, Common Lisp, C#

8:05 bobo_: LauJensen: hm, i cant find any rss link or similar?

8:05 LauJensen: bobo_: Your browser should pick it up automatically. Check out the footer on that Best In Class Tour blogpost

8:05 There's shiny new icon and a link

8:06 bobo_: hm, chrome didnt pick it up, weird

8:06 firefox did

8:07 LauJensen: thats odd. Its an old standard

8:09 spariev: LauJensen: what about FormLayout ? http://www.jgoodies.com/freeware/forms/index.html

8:10 it used to be good when i did swing development last time, like 5 years ago :)

8:10 LauJensen: spariev: Hadn't seen that before, but it looks nice

8:10 Oh how I miss the old days of Visual Studio and C#. I wonder why nobody just started with building UI systems equivalent to Winforms. GTK sucks, Swing sucks. Code generated UIs suck. You just want to drag and drop and design and be done with it

8:11 Qt is actually very close... then they gave up on Jambi

8:11 cinim0d: ['ol

8:12 fliebel: LauJensen: You mean you drag and drop Swing? I did it by hand… years ago. Jambi is still maintained open source I believe.

8:12 LauJensen: fliebel: 'maintained open source'

8:12 fliebel: No I dont drag and drop, but I want to

8:13 lpetit: hi

8:13 bobo_: netbeans has an awesome swing drag and drop editor

8:13 LauJensen: fliebel: If you're on ubuntu you likely have 'qt-designer' installed. Thats the kind of editor I want

8:13 bobo_: Does it spew out a .java file when you're done designing?

8:13 fliebel: LauJensen: I'm on Mac, but I have it installed, because I like QT better than TK in Python.

8:13 bobo_: LauJensen: yes, (and a .form)

8:13 LauJensen: bobo_: How are you driving that from Clojure?

8:14 bobo_: no clue, havent done any swing with clojure.

8:14 but might work. i think the .form is only for netbeans to make sense of stuff

8:14 LauJensen: I'll have to check that out once I get some time

8:16 fliebel: What is the best way to get the first element from a seq to satisfy f? I currently have (first (drop-while f))

8:16 cinim0d: fliebel: find-first

8:17 fliebel: cinim0d: Thanks

8:17 bobo_: some googling tells me cemerick has used mattise (netbeans gui editor) and clojure

8:17 cemerick: bobo_: indeed I have

8:18 fliebel: (doc find-first)

8:18 clojurebot: "clojure.contrib.seq-utils/find-first;[[pred coll]]; Returns the first item of coll for which (pred item) returns logical true. Consumes sequences up to the first match, will consume the entire sequence and return nil if no match is found."

8:18 bobo_: google knows theese logs way to good

8:18 fliebel: How comes find-first is not in here? http://clojure.github.com/clojure/clojure.core-api.html

8:18 LauJensen: bobo_: generally I try to be very productive by staying away from all of the tools cemerick uses. So far its worked great :)

8:19 bobo_: haha

8:19 Chousuke: fliebel: because it's in contrib? :)

8:19 fliebel: Chousuke: So then why did the above doc command work?

8:19 spariev: LauJensen: btw there is a GUI tool for Formlayout - http://www.formdev.com/jformdesigner/

8:19 not free, though

8:20 Chousuke: fliebel: Clojurebot's doc is special

8:20 fliebel: and I think it might have contrib loaded anyway

8:20 doc looks up vars in any loaded namespace, not just core

8:20 * cemerick sighs @ LauJensen :-|

8:20 cinim0d: fliebel: also, the bot specified that it was contrib.

8:21 LauJensen: cemerick: it was a joke ol buddy, come on now :)

8:21 fliebel: cinim0d: I saw that, after I asked :(

8:21 cinim0d: np

8:21 LauJensen: spariev: Looks too complex.

8:22 spariev: maybe, haven't used it

8:26 fliebel: Where can i read about the decomposition map thing in 1.2?

8:30 *destructuring

8:31 found it… partially

8:32 Chousuke: it's just & {map form}

8:32 and then the rest args will be expected to be key val key2 val2 ... which will be poured into a map and destructured like a normal map.

8:33 fliebel: Chousuke: So how do I destructure a normal map?

8:34 I did find {:keys [:list :of :keys]} but that seems so… I don't know...

8:34 Chousuke: ,(let [{:keys [a b]} {:a 2 :b 2 :c 3}] [b a])

8:34 clojurebot: [2 2]

8:34 Chousuke: oops, didn't mean to put two 2s

8:34 anyway

8:34 raek: ,(let [{x :a, y :b} {:a 1, :b 2}] (list x y))

8:34 clojurebot: (1 2)

8:35 Chousuke: or you can do {name :key name2 "string" name3 'symbol name4 5}

8:35 fliebel: raek: That looks more like I expected it to work. What is this :keys business anyway?

8:36 Chousuke: it's a shortcut

8:36 {a :a b :b c :c} is a very common form

8:36 fliebel: Okay...

8:40 raek: yes, :keys assume the the keywords have the same name as the symbols given

8:40 it is also possible to do a similar thing with strings

8:41 ,(let [{:strs [a b]} {"a" 1, "b" 2}] (list a b))

8:41 clojurebot: (1 2)

8:41 Chousuke: and symbols

8:41 (:syms)

8:41 raek: ,(let [{:syms [a b]} {'a 1, 'b 2}] (list a b))

8:41 clojurebot: (1 2)

8:41 Chousuke: you can also freely combine those as long as the names don't collide :P

8:41 fliebel: raek: Thank you! That makes sense to me :) Can you also combine :keys and :strs?

8:47 shoover: LauJensen: WinForms? If you enjoyed that maybe you should come back and check out WPF. You can drag and drop or type markup, and it's far more declarative and enjoyable to work with than WinForms

8:52 jjido: how do I implement a fork-join kind of parallel algorithm? Agents?

8:53 Chousuke: you could use ForkJoin? :P

8:53 It's available in library form for JDK6 too

8:54 jjido: Chousuke: thanks! Is there a doc?

8:54 Chousuke: probably somewhere

8:56 If you want to do it purely in Clojure I suppose agents might work.

8:56 LauJensen: shoover: Sounds good but Im not working with CLR in any way

8:57 Chousuke: you might have a thread do part of the work and then send the result to an agent which combines it with already finished stuff.

8:57 raek: jjido: what does "fork-join" mean? something like (let [f1 (future exp1) f2 (future exp2)] (+ @f1 @f2))?

8:58 or something more special?

8:59 jjido: Chousuke: yes I want something like that. raek: let me think

8:59 Chousuke: I wonder how the par branch is doing

9:00 raek: anyway, futures are a simple way to do some computations in other threads and then collect the results

9:00 Chousuke: rhickey implemented some interesting parallel vector ops with the JDK7 forkjoin library but it seems to have been forgotten :P

9:01 raek: pvalues and pcalls might also be worth checking out

9:03 jjido: raek: the result combine operation is repeated on all chunks recursively

9:03 I think there should be a specific chunk size which forks / joins

9:05 then it could be the scheme you describe

9:08 fliebel: Hmm, how is unit testing most commonly done in Clojure? I just came up with a funny idea.

9:08 raek: clojure.test, something like this: http://gist.github.com/570143

9:09 (variation of style exists, of course. this is just how I have done it.)

9:11 fliebel: raek: I just thought about sort of inline tests for side-effect-free functions. I'll cook something up.

9:12 raek: ,((fn [x] {:pre [(pos? x)]} (dec x)) 0)

9:12 clojurebot: java.lang.AssertionError: Assert failed: (pos? x)

9:13 raek: (dunno if this has to do with what you do, but fyi all fns can have pre and post conditions)

9:13 fliebel: raek: Something like that, but not jus constraining input and output, but rather have a map of arguments and expected results.

9:34 hmmm, what is the non-lazy variant of map? Or do i just wrap it in doall?

9:36 Chousuke: there is none, so yes, use doall

9:37 unless you mean doseq, but that doesn't produce a sequence :)

9:38 fliebel: Chousuke: http://gist.github.com/580719 <- also my inline-testing idea

9:39 In my opinion, it'd be far more pleasant to test some functions by just giving them an extra map of expected results.

9:39 Chousuke: yeah, use doseq

9:41 (doseq [{[input output] :tests} (meta f)] (assert (= (apply f input) output)))

9:41 (map destructuring there just for fun)

9:42 er, and also wrong.

9:42 never mind :P

9:42 I thought it was a good idea and then it wasn't.

9:42 fliebel: Chousuke: What's wrong?

9:42 Chousuke: (meta f) is not a seq

9:43 fliebel: Chousuke: So can't you destructure a map?

9:43 Chousuke: fliebel: in this there's no map to destructure.

9:44 any destructuring in doseq is applied to every element of the seq

9:44 which is the error in the above.

9:45 fliebel: ah, I see

9:45 Chousuke: so it has to be (doseq [[input output] (:tests (meta f))] (assert (= (apply f input) output)))

9:54 fliebel: Chousuke: It seems core/test does about the same as I wanted :-o So I only need to define a macro to add the data easily.

10:05 Huh, this is weird, I can make a defn with either the doc string or the arguments going first.

10:05 What is the preferred way?

10:06 chouser: a string after the args won't be a doc string, I think.

10:06 mrBliss: fliebel: if you put the argument first, the docstring is interpreted as part of the function

10:07 fliebel: right… stupid of me

10:22 nunb: Hi can someone point me to a comparison of Moustache vs Compojure routing? Moustache appears to yield a more composable structure.. but not sure how battle-tested it is.

10:24 LauJensen: nunb: I think its at least as battle-tested as Compojure. I don't know of any direct comparisons, but its a good topic for a future blogpost

10:24 I've deployed both Compojure and Moustache in professional solutions, more than once on both counts as well.

11:05 fliebel: Am I correct that app in Moustache returns a function that takes a ring request?

11:05 If so, what does a minimal request map look like?

11:21 jcromartie: I'm trying to duplicate a Ruby script in Clojure, and I am finding that the Clojure version is (surprisingly) much slower than the Ruby version.

11:21 it takes about 5x longer than the Ruby version

11:22 (paste on the way)

11:24 http://gist.github.com/580882

11:26 raek: fliebel: yes, the function returned takes a ring request and returns a ring response

11:26 fliebel: iirc, moustache probably just looks at the :url key

11:26 fliebel: raek: Cool :) Yea, and the request method, got it working :)

11:27 raek: I'm looking to (ab)use Moustache both as Ring middleware and as routing for something else.

11:30 AWizzArd: A very lightweight http client? I need to write my own headers and decide what method I want to use (Post, Put, Head, ...).

11:35 jcromartie: I revised the clojure version at http://gist.github.com/580882

11:35 to be a little nicer

11:38 nunb: jcromartie: how do you compare runtimes?

11:38 jcromartie: the time shell command

11:38 taking into account the startup

11:38 nunb: jvm startup cost?

11:38 oh

11:38 jcromartie: ruby takes 9 seconds, clojure takes 50

11:38 no room for JVM startup there :)

11:39 dnolen: jcromartie: hmm I wouldn't be surprised if the Clojure shell is the bottleneck, you're running sed on every match?

11:39 shell out I mean

11:39 jcromartie: yeah

11:40 but why would Ruby be so much better at that?

11:40 technically speaking

11:40 I know why it would make sense for Ruby to optimize that :P

11:41 fliebel: jcromartie: I wonder the same thing. I recently just printed hello world in a loop in both Clojure and Python, and Python was orders of magnitude faster.

11:41 dnolen: jcromartie: why do you need to use sed (I don't know what it does) ?

11:41 raek: I tend to do (into {} (for [[key val] seq] [(f key val) (g key val)])) *a lot*. any suggestions for an alternative?

11:41 2) or for the [f (g key val)] case?

11:42 grignaak: juxt!

11:42 fliebel: raek: What is that supposed to do?

11:42 jcromartie: dnolen: in this case, sed just prints a certain range of lines

11:43 grignaak: ,(into {} (map (juxt inc dec) '(1 2 3 4)))

11:43 clojurebot: {2 0, 3 1, 4 2, 5 3}

11:43 raek: something like map, but for the entries of a map

11:43 I think I saw a map-vals function in contrib once, but I can't seem to find it

11:44 fliebel: grignaak: Good to see juxt put to a use :)

11:44 raek: maybe (zipmap (keys m) (map some-fn (vals m))) would be sufficient in some cases

11:44 grignaak: doh! just saw the destructuring of key val

11:44 dnolen: jcromartie: why not just use Clojure for that? UNIX is all about stringing different commands together, JVM is all about working within the JVM. Will probably end up being much faster than Ruby then ;)

11:45 jcromartie: yeah

11:49 arohner: jcromartie: my guess is, you're spawning a new shell for each call to (sh)

11:49 jcromartie: whereas Ruby does...?

11:49 AWizzArd: clojure.contrib.http-agent was deprecated. Is there a new http client somewhere?

11:50 jcromartie: woo hoo!

11:50 it's way faster now

11:52 ohpauleez: AWizzArd: I'm not sure where in contrib it is, but http://github.com/technomancy/clojure-http-client and http://github.com/neotyk/ahc-clj are cool. If you need auth support or more features, just use HttpClient

11:52 dnolen: jcromartie: what did you do?

11:53 AWizzArd: ohpauleez: HttpClient <== Apache Project?

11:53 ohpauleez: yeah

11:53 jcromartie: dnolen: (->> (read-lines file) (take end-n) (drop (dec start-n)))

11:53 ohpauleez: It's the only one I know of that you can set the post body, auth support, etc

11:53 dnolen: jcromartie: nice, how many seconds does it take now?

11:54 chouser: jcromartie: what JVM are you using?

11:54 jcromartie: chouser: Mac OS X 10.6 default

11:54 dnolen: now it's like 1/3 to 1/4 the time of Ruby

11:55 arohner: jcromartie: what did you change?

11:55 jcromartie: arohner: take'ing and drop'ing from duck-streams/read-lines instead of shelling out to sed

11:55 shelling out kills it

12:00 hey chouser: you wrote shell-out. is there no way to use pipes with it?

12:01 slyrus: all of the clojure http clients I've found are wrappers (in some cases wrappers upon wrappers). A drakma equivalent would be nice.

12:01 kjeldahl: Suggestions for most elegant way to express: (if-not (nil? expr) expr someothervalue)

12:02 chouser: jcromartie: no, there isn't.

12:02 hiredman: (or expr1 expr2)

12:02 kjeldahl: hiredman: thanks

12:03 AWizzArd: slyrus: there was a http client in Contrib, I don't know why it was removed.

12:03 Raynes: kjeldahl: Remember that 'nil' is false in Clojure. You rarely have to explicitly check if something is nil with niL?

12:03 nil?*

12:03 chouser: jcromartie: would a (with-sh [[in out err] ("sed" ...)] ...) sort of thing work for your use case?

12:04 apgwoz: ,(false? nil)

12:04 clojurebot: false

12:04 Raynes: -> (if nil 0 1)

12:04 sexpbot: => 1

12:04 kjeldahl: Raynes: Thanks. Very elegant.

12:04 ohpauleez: (boolean nil)

12:04 apgwoz: ah, yes

12:05 ohpauleez: will be false

12:05 apgwoz: that's what i was missing

12:05 ,(false? (boolean nil))

12:05 clojurebot: true

12:05 ohpauleez: there it is

12:13 chillitom: i hear all the cool kids are in here..

12:13 anyone want to suggest a simple little algorithm for me to try cutting my clojure teeth on?

12:14 chouser: chillitom: I always recommend projecteuler.net

12:14 ohpauleez: chillitom: What are you coming from?

12:15 I sometimes suggest a collective intelligence algo on a simple web system.

12:15 like chouser said, euler is nice. Gives you a chance to take a simple algo, then type it, then parallelize it

12:16 Anything you choose, you'll want to be able to play with the data structures a lot, and the concurrent stuff.

12:17 I also recommend watching the video/presentation called Are We There Yet? (http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey)

12:17 fliebel: chillitom: I like this one: http://projecteuler.net/index.php?section=problems&id=11 Not to much math and a lot of data.

12:18 Enlive is killing me… deftemplate gives me a nullpointer for everything I do, even with no selectors in it or copying an example from the web.

12:19 I tried entering an absolute path to my file, nothing!

12:21 chillitom: chouser: euler is a bit too mathematical for me.. primes i don't find that interesting (although i know i should)

12:21 ohpauleez: coming from pretty much everything.. c,java,c#,haskell

12:22 ..ruby,python

12:22 chouser: chillitom: fair enough

12:23 ohpauleez: chillitom: What types of things do you typically write?

12:23 chillitom: chouser: did you used be be a big cheese in ##java?

12:23 i recognise your name

12:23 ohpauleez: I would just do a weekend project, a parallel web scraper is nice (takes less than a day)

12:24 chillitom: ohpauleez: that's a good idea and relates nicely to my day job

12:24 chouser: chillitom: goodness, no.

12:24 chillitom: chouser: no offence intended ;-)

12:25 chouser: :-)

12:25 ohpauleez: chillitom: You'll want to look at enlive, get it working, then add agents (you'll be blown away), then type-hint it. If you loop on a data structure you may get to play with transients

12:26 If you're a guy who totally digs performance, time how each approach takes, and get ready to be blown away

12:26 :)

12:27 jjido: what is enlive?

12:27 ohpauleez: enlive is a selector based templater/scraper: http://clojuredocs.org/Enlive/net.cgrand.enlive-html

12:28 project at http://github.com/cgrand/enlive

12:28 jjido: html only?

12:28 LauJensen: jjido: also xml (no namespaces though)

12:29 raek: enlive example (title fetching): (-> "http://clojure.org/&quot; URL. html-resource (select [:title]) first :content first)

12:29 jcromartie: chouser: I don't think so, doing it in Clojure is much faster than launching many shells

12:30 raek: it uses tagsoup for the html parsing, so it can consume "street HTML" too

12:30 jjido: I would like to look how to parallelise the merge-sort I wrote, I am still not clear what Clojure offers for that

12:30 raek: but as the programmer, you see a fixed element tree (with all html, head and body tags properly placed)

12:34 ohpauleez: jjido: You could use futures and promise and do each part in a different thread

12:34 You could also abuse agents and do the same thing

12:35 you could possible use pmap, depends on how you wrote your mergesort

12:35 possibly*

12:35 bobo_: hm, anyone using cake in ubuntu?

12:35 chillitom: raek, i was gonig to ask if tagsoup was behind it, i've used that lib before, v effective

12:36 jjido: ohpauleez: you need Java to start threads?

12:36 ohpauleez: nope, ,(doc future)

12:36 chouser: jcromartie: I meant for piping to shell commands

12:36 ohpauleez: ,(doc future)

12:36 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

12:36 jcromartie: hmm, posisbly

12:37 chouser: hm ... actually, I think I just had a better idea.

12:37 jcromartie: but sometimes I just need a bunch of pipes and redirects, etc. :)

12:37 bobo_: https://gist.github.com/b239769d7f21d7ef59f7 anyone have any clue on how to solve that?

12:37 raek: (doto (Thread. (fn [] ...)) .start)

12:37 jjido: raek: looks fine

12:38 raek: clojure functions implement runnable, so interop is pretty painless in this case

12:38 ohpauleez: jjido: http://www.michaelharrison.ws/weblog/?p=239

12:38 chillitom: i learnt haskell about three years ago and i remember picking it up in about a week.. Clojure looks much easier and it's taking me weeks, i think the old grey matter has slowed down

12:38 raek: futures has the advantage that they can return a value back

12:38 fliebel: bobo_: Check the path?

12:39 ohpauleez: jjido: that you can deref using @

12:39 bobo_: fliebel: but shouldnt gem install handle that for me?

12:39 i know 0 about ruby/gem

12:39 raek: (doc future)

12:39 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

12:40 laurus: Is it OK to use Clojure with OpenJDK?

12:40 ohpauleez: laurus: I use JDK7 with my clojure

12:40 works just fine for me

12:40 fliebel: bobo_: It should, but apparently it didn't. So make sure the place ruby puths the bin is on the path, and before the ubuntu thing that catches the missing things.

12:40 laurus: ohpauleez, OpenJDK or SunJDK?

12:40 ohpauleez: laurus: OpenJDK

12:40 laurus: Excellent, that's great to hear!

12:41 ohpauleez: That said, I also use SunJDK (Apple branded) for some stuff

12:41 laurus: :)

12:43 Thanks for the info!

12:43 ohpauleez: laurus: totally welcome

12:44 jjido: ping me if you run into trouble

12:44 fliebel: Why does Enlive only look on the cp for files?

12:45 ohpauleez: fliebel: I don't think I was aware it did that. Maybe hit up the clojure-web list/google group

12:45 jjido: ohpauleez: ok

12:47 chillitom: ohpauleez: watching are we there yet on your recommendation, i love rich's presentations

12:47 fliebel: ohpauleez: Enlive readme: if you specify your resources as strings they will be searched on the classpath

12:47 ohpauleez: chillitom: They are awesome, and I feel like that one gets to the heart about the Clojure mindset and design philosophy

12:49 raek: fliebel: use (java.io.File. "filename") or (clojure.java.io/file "filename")

12:50 the JVM doesn't have a strong notion of current working directory, so absolute paths might be a good idea

12:50 also, leiningen makes the resources/ directory available on the classpath

12:50 ohpauleez: re: resources directory, would explain why I never ran into this issue

13:41 amalloy: i want to know who was so cruel as to put map, reduce, filter, and join into PHP but make them painful to use. it'd almost be better if they weren't there at all

13:42 ohpauleez: amalloy: haha, I'm currently working on a PHP project with work. I hear ya

13:50 bobo_: amalloy: +1 on that

13:55 LauJensen: amalloy: What makes them so painful?

13:56 amalloy: closures aren't available (until 5.3, in which they exist but are bulky)

13:57 bobo_: if you can call "put your code in a string" as a closure

13:58 or is the create_function 5.3?

13:59 amalloy: not sure

14:13 mfex: hi all

14:14 is there an unfold function somewhere in clojure or contrib?

14:14 LauJensen: mfex: what would unfold do ?

14:15 mfex: it is the opposite of reduce

14:15 or the opposite of fold, see http://en.wikipedia.org/wiki/Anamorphism

14:17 raek: can you show an example input and output?

14:19 mfex: this is the equivalent of iterate from the wiki: (defn iterate-unfold [f x] (unfold (fn [a] [a (f a)]) (fn [_] false) x))

14:19 I want to use it in an answer for this question on the group: http://groups.google.com/group/clojure/browse_thread/thread/f1593f492759e66b#

14:20 bobo_: wow, 1.2GB of memory used by a new empty cake project with swank running?

14:21 raek: my clojure processes often start at ~700 MB if I don't pass JVM options

14:21 fliebel: bobo_: So all those EMACS acronyms still apply?

14:21 raek: then I can get them down to about 150 MB

14:21 bobo_: fliebel: acronyms? :-)

14:21 lein swank uses 300MB

14:22 same project

14:22 raek: (this is when starting a repl and swank)

14:22 bobo_: oh well, memory is made to be used

14:23 fliebel: bobo_: http://en.wikipedia.org/wiki/Emacs#Performance

14:23 bobo_: cute :-)

14:23 lancepantz: bobo_: you tweak the jvm options and get the memory footprint down

14:23 *could

14:24 bobo_: lancepantz: i dont realy care, im jsut very suprised

14:24 and i cant spell, guess im running out of memory

14:24 lancepantz: you're not the first to bring it up, its a legit beef

14:25 if you do and find anything useful, send a pull request :)

14:25 bobo_: :-)

14:25 lancepantz: there's a section about jvm opts in the readme if that's of help

14:26 LauJensen: .cake/config => project.java_opts = -Xmx256M

14:26 lancepantz: what always shocks me is the memory usage of growl on os x

14:27 bobo_: why isnt -Xmx256M default if it is an improvement?

14:27 lancepantz: it was like 8gb

14:28 bobo_: 8gb? thats alot :-p

14:28 LauJensen: bobo_: its a improvement if you have a tiny little computer with no memory, if you have 4Gb+, you dont care

14:28 I want my JVM to have 700+ memory :)

14:28 bobo_: yeh, as i said, i dont care, im just supprised :-)

14:28 LauJensen: bobo_: yea right, you're trying to code Clojure on the ipad I know you are!

14:28 bobo_: i wish!

14:29 lancepantz: hah, i'm going to add that to the cake readme

14:29 more believable than commodore 64 anyways

14:30 bobo_: i think i miss the default core.clj file lenigen creates.

14:30 lancepantz: it does that?

14:30 bobo_: yes

14:30 lancepantz: does it create it project/src/project/core.clj or project/src/core.clj?

14:31 bobo_: TestProject/src/TestProject$ ls

14:31 core.clj

14:31 lancepantz: cool

14:31 bobo_: and it just contains (ns TestProject.core)

14:31 lancepantz: yeah, that is a good idea

14:32 LauJensen: well, if everybody wants a core.clj I guess its a good idea

14:32 lancepantz: i'm sure that's what ninjudd was thinking

14:32 chouser: mfex: I'm not sure exactly what you want -- you've looked at 'iterate'?

14:32 bobo_: if most people want it atleast, but should probably be able to turn it of then

14:49 Raynes: ,(dosync (alter (ref 0) inc))

14:49 clojurebot: 1

14:49 chouser: *bam* STM

14:49 ohpauleez: rad

14:50 is that new to clojurebot?

14:50 chouser: nope

14:50 ohpauleez: ah, just showing the STM some love

14:51 chouser: I guess. I dunno what Raynes is up to.

14:51 wwmorgan: ,(get 1 1) ; shouldn't this raise a type error?

14:51 clojurebot: nil

14:51 Raynes: I'm playing around with sandboxing in sexpbot, so I wanted to make sure that worked in clojurebot.

14:52 LauJensen: -> (time nil)

14:52 sexpbot: java.lang.SecurityException: Code did not pass sandbox guidelines: ()

14:54 LauJensen: wwmorgan: it ends up running

14:54 public final Object valAt(Object key) {

14:54 return valAt(key, null);

14:54 }

14:54

14:54 I wonder if the second param isnt an imposed default

14:54 similar to

14:54 ,(get {:a 5} :b)

14:54 clojurebot: nil

14:55 wwmorgan: LauJensen: I mean in a philosophical sense, shouldn't a type error be the correct behavior?

14:55 LauJensen: oooh you're being philosophical...

14:55 chouser: wwmorgan: I'm pretty sure it's not accidental

14:56 LauJensen: chouser: Yea Im feel confident as well, but I still wonder why

14:56 wwmorgan: I can maybe see the argument for (get nil 1) returning nil rather than raising an error, but (get 1 1) is just a wrong thing

14:56 LauJensen: I guess its like (count nil), makes code more robust and concise

14:57 chouser: unless it's more like (count 34) which does throw a type error

14:58 LauJensen: hmm, we did I suddenly get the feeling we're in PHP land?

14:58 s/we/why/

14:58 sexpbot: <LauJensen> hmm, why did I suddenly get the feeling why're in PHP land?

14:58 wwmorgan: I guess there's an implied /g in sexpbot's s/

14:59 LauJensen: wwmorgan: yea the g was just bloat, Raynes killed it

14:59 wwmorgan: contains? does the same thing actually, which is more insidious, because (contains? 1 {1 2}) returns nil when it could throw an exception

15:00 chouser: ooh

15:00 compile time assertions could be made about code you don't own.

15:01 wwmorgan: ,(contains? (transient {1 2}) 1) ; This used to be a bug. I don't know whether it's been fixed.

15:01 clojurebot: false

15:01 chouser: wouldn't that be fun? To declare somewhere that, in this code base, contains? and get may only be called on objs that implement Associative or whose type is unknown.

15:02 then as soon as you say (fn [] (contains? 1 a)) you get a compile-time error.

15:04 hiredman: (let [contains? (constantly true)] (fn [] (contains? 1 a)))

15:04 chouser: don't worry, it wouldn't be fooled.

15:04 hiredman: oh, ok

15:05 maybe arkham could do it

15:05 chouser: that is, if compile time assertions could be fooled by things like that, then I think they'd be pretty useless.

15:05 and since they don't exist yet, we can ascribe to them any fantastic behavior we want yay

15:06 arkham could do it at "compile time" or does it have such a stage?

15:06 hiredman: well, it could do static analysis

15:06 chouser: it starts with what the reader produces?

15:06 hiredman: yes

15:07 (all mostly in theory too)

15:07 chouser: oh, I thought you had it mostly working

15:07 hiredman: but import generator does something similar

15:08 chouser: did you consider using compiler-produced analysis trees?

15:08 hiredman: nope

15:09 I hadn't really considered it at all

15:09 chouser: fair enough

15:09 I don't know if it would be of any benefit at all

15:09 and they're certainly rather impenetrable right now

15:09 andyfingerhut: Does anyone have any experience with Java performance analysis tools that get into details of caching performance etc. on multi-core machines, and deal with multi-threaded Java programs well? To be accurate such a thing would have to have some info about the particular processor arch you are running on.

15:14 lancepantz: andyfingerhut: do you use jmx?

15:15 i don't know if you can get that level of detail out of it, but its always had what i needed

15:15 bobo_: visualvm can tell you alot, not sure if its enough

15:15 andyfingerhut: I believe I used jmx briefly, but at the time wasn't looking for that kind of info out of it.

15:16 lancepantz: jconsole has all sorts of stuff i could never make sense of as well

15:17 bobo_: visualvm is jconsole on steroids

15:17 lancepantz: hmm,

15:17 i'll have to check it out

15:19 LauJensen: bobo_: IIRC jconsole and jvisualvm complement each other. jconsole had more memory info last time I checked

15:19 bobo_: i was at a jrockit talk last night, they claimed their stuff can do alot

15:19 LauJensen: I dont think they were wrong :)

15:19 bobo_: cant remember what it was called, jrockit console or something

15:21 and jconsole might have more memory info, was probably a year since i used any of them

15:22 andyfingerhut: Thanks for the pointers: jmx, jconsole, visualvm (maybe a superset of jconsole, maybe not), jrockit console. I'll start by Googling through their docs for keywords first.

15:23 bobo_: visualvm and jconsole is a part of jdk, so you probably have them installed already

15:24 andyfingerhut: I've found it challenging in some cases to determine why some multi-threaded programs that are embarrassingly parallel (i.e. no interaction at all between the threads in terms of message passing, locking, or anything like that) do not achieve a speedup equal to the number of cores.

15:25 bobo_: they showed how to find exactly that at the presentation i was at yeasterday :-)

15:25 chouser: I've used yourkit, but not nearly to the extent of its abilities.

15:25 andyfingerhut: If the cores share a cache, that seems like a possible explanation, but I'd like to figure out how to verify that guess with data.

15:26 bobo_: ive seen alot of love been given to yourkit

15:29 andyfingerhut: bobo_ Is there a publically-available version of the presentation you attended yesterday? Or was it a private sales demo or something like that?

15:31 bobo_: i might have misunderstood what you wanted. but anyway, it was at a user group. but dont know if slides are anywhere.

15:31 andyfingerhut: Do you have a name/email/other contact info for the presenter?

15:32 bobo_: they will give it at javaone next week atleast

15:32 they are most likley willing to show you more if you are a company with money :-)

15:33 was the authors of: http://www.amazon.co.uk/Oracle-JRockit-Definitive-Marcus-Hirt/dp/1847198066/ref=sr_1_1?ie=UTF8&s=books&qid=1284579092&sr=8-1

15:34 andyfingerhut: Understood that being a company with money can get you good tech support and help. I've been there :) But right now I'm looking at what I can do for free. Not looking for handouts, but willing to take advantage of free trials if available.

15:34 bobo_: http://www.oracle.com/technetwork/middleware/jrockit/downloads/index.html

15:34 seem to be download links

15:34 andyfingerhut: bobo_ Thanks much.

15:35 bobo_: it probably requires you to use jrockit vm aswell. no clue about that

15:52 hiredman: is there nothing in contrib that does bytes->hex string and hex string -> bytes?

15:53 ordnungswidrig: bytes in an array?

15:53 hiredman: right

15:54 ordnungswidrig: (map Integer/toHexString array)

15:55 hiredman: well, I have functions that do both

15:57 ordnungswidrig: would be a nice add-on for contrib.

15:57 hiredman: right

15:58 but in their own namespace? or an existing one?

15:59 ordnungswidrig: would you mind to address the general case of radix conversion?

16:00 hiredman: yes

16:00 (as in no)

16:01 ordnungswidrig: only hex?

16:02 hiredman: this algorithm is more about speed (makes use of a lookup table) than generality

16:06 jcromartie: (map (partial format "%02x") bytes)

16:06 ordnungswidrig: hiredman: then I'd expect it somewhere in a crypto packages next to message digests and so on :)

16:07 jcromartie: yes, that's where I always use it

16:07 ,(map (partial format "%02x") (.getBytes "Hello, World!"))

16:07 clojurebot: ("48" "65" "6c" "6c" "6f" "2c" "20" "57" "6f" "72" "6c" "64" "21")

16:08 hiredman: jcromartie: I haven't done measurements, but I think just about anything would outperform format

16:09 jcromartie: I'm usually only converting one byte array at a time

16:10 hiredman: would you be interested in doing some comparisions of the format method versus my code?

16:10 jcromartie: sure

16:10 mine is "fast enough" :)

16:11 hiredman: http://gist.github.com/581363

16:13 jcromartie: I'd cheat

16:13 memoize format

16:14 ordnungswidrig: hiredman: holy crap, where does one need such fast byte->hex methods?

16:15 hiredman: ordnungswidrig: *shrug*

16:15 the code we write today is the building blocks of the code we write tomorrow

16:15 ordnungswidrig: I mean, when things must be fast, who would use hex-digit encodings?

16:17 hiredman: I ended up with this while thinking about a process that involved taking uuids (keys) stored as strings, getting the numeric value and using a mod to partition the keys

16:21 ordnungswidrig: sharding?

16:23 hiredman: similar

16:23 arkh: fwiw, I made a small predicate that tests to see if a string matches a private IP address in the ranges defined by RFC 1918 - still very much learning clojure and/so criticisms welcome: http://gist.github.com/581391

16:26 ordnungswidrig: arkh: either use regex groups and drop the split or make a split and drop the regex :)

16:28 arkh: ordnungswidrig: that's a good idea; I'd probably opt to go with groups. Thanks

16:32 jkkramer: arkh: (if (every? true? (map #(octet-range %) [b c d])) true) can be just (every? octet-range [b c d])

16:32 raek: arkh: if-let + destructuring + re-find + groups is my favourite approach

16:33 (small detail: predicates (functions that return booleans) are usually named with an ending questionmark)

16:34 grignaak: right and can drop the ifs around the ands

16:35 ordnungswidrig: I gisted a comment

16:36 arkh: jkkramer: I'm surprised I missed that. Like I'm trying to win a verbosity contest o.0

16:36 raek: (if-let [[_ a b c d] (re-find #"^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$" ip)] ...)

16:36 sdeobald: .

16:36 Raynes: Hey, sorry to bother you, but do you have any documentation on running tryclojure?

16:37 grignaak: also gisted a comment

16:37 arkh: raek:, grignaak: thank you

16:38 grignaak: arkh: fixed formatting on comment (was thinking pastie, not gist)

16:41 ordnungswidrig: I gisted again, now with destructuring: (if-let [[a b c d :as qs] (map #(Byte/decode %) (clojure.string/split ip #"\."))] ...

16:41 arkh: I think my strictly imperative language background is evident in my code : (

16:42 all these suggestions rock though : )

16:43 ordnungswidrig: arkh: you will get comfortable with functional style. After that you'd better hope then not to have to use an imperative language again. The other way is harder.

16:44 chouser: it's not that it's hard to write imperative code after you know how to do it functionally, it's just hard to keep your lunch down while you're doing it.

16:45 ordnungswidrig: chouser: exactly

16:46 I've "annoyed" team members by using a Maybe-Monad type in a java project. But it safed by a lot of NPEs at runtime.

16:49 grignaak: ordnungswidrig: me too, mine was called MaybeSo and MaybeNot

16:50 ordnungswidrig: if java had function types or sth like closures it would have been prettier. the incomplete type system doesn't make it better as an addition.

16:50 bobo_: hm, how did thoose monads look? and how did you use them? i dont know much about monads, but dont think ive seen any in java?

16:52 chouser: I don't see monads here, but this may give you a sense of what general functional programming looks like in a language not designed to support it: http://functionaljava.org/

16:53 ordnungswidrig: bobo_: I used them as a NPE safe alternative to "null". Maybe.just(value).map(new Function<String, Integer>{){Integer apply(String s) {return s.length();}}).map(new Function<Integer, Integer>(){Integer apply(Integer v) {return v*v;}})

16:53 bobo_: dick wall of javaposse fame has a talk on parleys on functional java aswell...

16:53 ordnungswidrig: so pretty much like Some in scala? but with the horrible syntax of java?

16:54 ordnungswidrig: bobo_: yes, I borrowed maybe from haskell, in scala it is Some

16:54 bobo_: ok, thanks, much clearer to mee!

16:55 ordnungswidrig: the syntax is not that worse, IntelliJ reduces the noise for me. Missing type inference and type erasure and lack of higher order types is what me bugs in practice.

17:17 jjido: so I added promise and send-off to my merge-sort algorithm, it sorts fine but the (agent nil) must be still running because it never terminates...

17:18 ohpauleez: jjido: did you shutdown the agents?

17:18 jjido: ohpauleez: the agents just deliver a value

17:18 ohpauleez: also, did you try deferencing futures as a possible solution too?

17:19 at the very end, you need to: (shutdown-agents)

17:20 jjido: code: http://pastebin.ca/1941654

17:20 thanks ohpauleez

17:21 ohpauleez: you shouldn't have to pass off the futures to agents

17:23 ie: you can use agents, (await) on the agents, and then merge their results. Or use futures and merge @your-future, which will block until the future is done

17:23 so you can continue to use promises, but in this case, you may not need to

17:24 that said, the code there should work (essentially you're running a thread via another thread), but (shutdown-agents) should fix your agent

17:24 nicely done jjido this is a good example

17:24 jcromartie: hiredman: (def byte-str-chunk (memoize (fn [b] (format "%02x" b))))

17:24 hiredman: (defn byte-str [bytes] (apply str (map byte-str-chunk bytes)))

17:24 should be pretty fast

17:25 ohpauleez: If you want to keep exploring, you should be able to create a version that uses pmap, mapping the merge to partitions of the entire list, then you can apply the the final merge to the result

17:26 (apply merge-sort-lists (pmap merge sort (partition my-data)))

17:27 rather: (apply merge-sorted-lists-rec (pmap merge-sort-rec (partition 5 my-data)))

17:28 arkh: new gist is up for 'is-rfc1918?'. ordnungswidrig's version is epic: http://gist.github.com/581391

17:29 raek: minor detail: when there is no false branch in an 'if', it can be marked by using 'when' instead

17:30 chouser: s/can/should/

17:30 :-)

17:30 raek: also, I misread the indentation

17:30 the 'and' and the 'or' are not indented the same

17:31 arkh: good call on the if/when; the or is in the and, though

17:32 jjido: ohpauleez: I don't understand what you suggest. What do you mean "you're running a thread via another thread"

17:33 ohpauleez: a future is a separate thread, and an agent is a separate thread. So when you're sending the future to an agent to gather the results, you're using two threads. Unless I'm making a mistake (which may be true)

17:35 grignaak_away: is future different in clojure and java? in java a future is just a _promise_ of a return value at some later date.

17:36 although typically returned by a executor, it need not be. it could be a thunk!

17:36 ohpauleez: ,(doc future)

17:36 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

17:36 jjido: I don't need explicit agents then?

17:36 * grignaak humbles himself

17:36 arkh: raek: is that indentation ok?

17:37 ohpauleez: grignaak: in clojure, that's just called a promise

17:37 ,(doc promise)

17:37 clojurebot: "([]); Alpha - subject to change. Returns a promise object that can be read with deref/@, and set, once only, with deliver. Calls to deref/@ prior to delivery will block. All subsequent derefs will return the same delivered value without blocking."

17:37 ohpauleez: jjido: right, you don't need the agents

17:41 based on implementation, the promises are optional too

17:42 hiredman: no

17:42 clojure futures are java Futures

17:43 ohpauleez: see, I told you I might be wrong with some of this :)

17:45 raek: arkh: let me check...

17:45 the or is now correct

17:46 arkh: raek: thank you

17:46 raek: but the equality sign on the row below should be aligned with the one on the or-line

17:46 (or (= ...)

17:46 (= ...))

17:47 ohpauleez: jjido: Things working out ok?

17:47 arkh: raek: yes and done : )

17:48 raek: emacs (and other editors, I hope) can do this automatically

17:48 in emacs you can simply select the text and press tab

17:49 jjido: ohpauleez: look http://pastebin.ca/1941677

17:49 can't figure what is a good parallel cutoff

17:50 arkh: using vim right now : / I'd probably use emacs now that I know people re-map their keyboard to swap caps lock and ctrl (or just make caps lock a third ctrl)

17:50 that's a recipe for carpal tunnel otherwise

17:50 ohpauleez: jjido: looks awesome to me. The cutoff point is usually your nonfunctional requirement (when you get it fast enough)

17:51 you could add (partition) in there

17:51 based on the size of the list

17:51 vector*

17:51 jjido: ,(doc partition)

17:51 ohpauleez: ohhh, nvm, I see what you're doing

17:51 clojurebot: "([n coll] [n step coll] [n step pad coll]); Returns a lazy sequence of lists of n items each, at offsets step apart. If step is not supplied, defaults to n, i.e. the partitions do not overlap. If a pad collection is supplied, use its elements as necessary to complete last partition upto n items. In case there are not enough padding elements, return a partition with less than n items."

17:52 jjido: how do I repeat a function 10 times? For better time measurement

17:53 amalloy: ,(dotimes [_ 10] (* 2 1))

17:53 clojurebot: nil

17:56 lpetit: I'm currently annoying my whole team (ok, that's just one person :-) ) by having written some "way" to manipulate classes in an immutable/editable way. Defined some kind of INonEditable / IEditable pair of interfaces. All my domain model classes implement INonEditable, and have peers which implement IEditable. INonEditable keeps a pointer to the "reference" IEditable, and is created by...

17:56 ...calling createEditable() on the IEditable interface (thus allows polymorphism in deep object graphs). Of course there's no real O(anything) / efficient structure sharing, but it does the trick ! It also allowed to have some nice polymorphic reset() createNonEditable() isDirty() methods on IEditable interface :-)

17:57 jjido: goes faster on my machine with less parallelism (ie. cutoff value higher)

17:58 ohpauleez: jjido: you want 2 * number of cores

17:58 usually

17:58 wow... let me rephrase that

17:58 jjido: isn't that automatic?

17:59 ohpauleez: # of threads at any given time shouldn't exceed 2 * # of cores. And your computation time has to be longer than thread startup time (or acquisition from pool) at your smallest piece

17:59 as two general rules of thumb

18:00 jjido: how big is your dataset?

18:01 jjido: ohpauleez: I just have 200 values. I think my machine likes 100 elements partition

18:01 lpetit: "# of threads at any given time shouldn't exceed 2 * # of cores" : is this empirical ? explainable ? If empirical, what are the implicit assumptions on the "context" ?

18:02 ohpauleez: ^^^

18:02 ohpauleez: jjido: pass it something like (range 1000 0 -1)

18:04 lpetit: let me dig up a paper for you. You can generate this empirically. It was one of the first labs I had to do in a concurrent class using MPI

18:04 I believe the ideal number of long running threads is the number of cores available

18:05 the *2 is used for shorter running threads to prime the thread for execution while a running thread finishes up

18:06 lpetit: ohpauleez: ok, but doing experiments generally comes with experiment context, so that people know when they are in the same experimental conditions and if the next result have any chance to be predicted as being the same, no ?

18:06 ohpauleez: no, that's correct

18:06 ie: if there's io latency

18:07 and so on

18:07 lpetit: ohpauleez: ok, so it's empirical, I guess tonight I'm too tired to be able to remind anything else but that, thx :)à

18:07 :)

18:07 ohpauleez: :)

18:08 * lpetit is currently motivating one the of ccw team member to add leiningen support to ccw

18:09 ohpauleez: that's a good thing to motivate

18:09 lpetit: Is it true to say that most (if not all) lein commands are generally short of additional command line argument (and that generally the "configuration part" of the command belongs to project.clj) ?

18:10 ohpauleez: that is true

18:10 I would even say all, with the exception being dependencies that add commands to lein

18:10 like nailgun for example

18:12 lpetit: so the simplest GUI for lein (given that we're already in the context of some Eclipse/lein project) is a menu entry somewhere, with one submenu entry for each lein task, without additional needed input from the user

18:12 ?

18:13 hiredman: hard to say

18:13 lein test can take the namespace of tests to run as an argument, which is very useful

18:14 ohpauleez: and lein interactive would need a shell-like window. lein compile can take namespace args too

18:15 lpetit: I would look at similar projects, like how eclipse handles make, ant, maven (I'm not familiar eclipse)

18:16 lpetit: another option: would it be safe to eagerly 'require the tasks namespaces, just for then being able to dynamically inspect the task's signature, and dynamically inferring from it whether it has args or not, and if yes, dynamically create an appropriate Form for the user to type arg values ?

18:17 ohpauleez: Could you have a settings panel somewhere, and then use the menu+hot key approach?

18:17 lpetit: ohpauleez: yes, but sometimes those things are overly complex for the simples (and more often used) use cases. But indeed I'll look at them, though more at maven's ones than ant's ones (ant being so general and low level, its GUIs tend to be very generic and *heavy*)

18:17 ohpauleez: good point

18:18 technomancy: lpetit: there are already fns in leiningen.core that can inspect a task and tell if it needs a project arg or not

18:19 lpetit: of course, there would be menu + hot key. I also guess that once the user has entered values for a task with arguments, those values could be already filled the next time. And an alternate hot key approach for automatically using the last values without going through the popup

18:19 technomancy: lpetit: in fact, leiningen.core/apply-task might be what you're looking for

18:19 lpetit: technomancy: my hero !

18:19 arohner: a little bit off topic question, but I'm calling java code from clojure, and the java code throws an exception, that doesn't contain file names or line numbers. What could cause that? IIRC, this code was compiled "normally" using ant

18:19 lpetit: technomancy: and what about auto-discovery ?

18:20 technomancy: lpetit: leiningen.help/tasks will list them

18:20 ohpauleez: arohner: it sounds like the java code wasn't compiled with debug info. That's the only thing I know that can do that

18:20 happens with you pass optimization flags sometimes

18:20 hiredman: arohner: I don't believe exceptions contain that information, you have to look at the stacktrace

18:21 arohner: hiredman: java code threw an exception, I caught it in clojure and did exception.printStackTrace()

18:21 lpetit: technomancy: even those who are spread over plugins as dependencies, scripts directly put by the user in his project's src/leiningen package, and those placed in %LEIN_HOME%/plugins ?

18:22 technomancy: lpetit: should catch them all; it walks the classpath

18:22 ohpauleez: arohner: what is the ant command and options used to compile the code?

18:23 jjido: ohpauleez: I used a dataset with 1000 ~ random numbers

18:23 arohner: ohpauleez: <javac srcdir="." destdir="${classes.dir}" classpathref="classpath" />

18:23 ohpauleez: arohner: totally bizarro. I've got nothing

18:23 lpetit: technomancy: ok, by opening the jars, etc. ? BTW, does it also work if plugins as jars do not contain the .cljs, but just the AOT compiled version of the plugin ?

18:23 ohpauleez: jjido: alright! How'd it run?

18:24 jjido: same, I need to use half the total size as cutoff

18:24 technomancy: lpetit: it has to have the source

18:24 never heard of an AOT'd lein plugin

18:25 source in jars is fine

18:26 lpetit: technomancy: of course, ability to guess namespaces from AOT compiled classes only requires to depend upon an implementation detail of AOT.

18:26 arohner: ohpauleez: the ant docs say javac takes an option of debug=#{true,false}, and defaults to false. Rebuilding the java now...

18:26 lpetit: technomancy: fine by me.

18:27 ohpauleez: arohner: ahh, keep me posted, I'd be interested to see what happens here. I've never run into this before

18:27 lpetit: technomancy: I just wanted to know the current capabilities. I imagine that leiningen.help/tasks has to load (err require) the plugin in the VM to easily get the docstring ?

18:28 s/the docstring/its docstring/

18:28 sexpbot: <lpetit> technomancy: I just wanted to know the current capabilities. I imagine that leiningen.help/tasks has to load (err require) the plugin in the VM to easily get its docstring ?

18:29 technomancy: lpetit: yeah, correct. the help task is pretty short; less than 40 lines; should be easy to understand how it works.

18:30 lpetit: technomancy: yep, sorry, should ask the source first. Difficult to resist the temptation to directly ask the master of the source, though :)

18:32 Ok, so it seems like everything is already there to quickly get something interesting, and pretty much automagic, cool !

18:32 must leave, cu and thank you all

18:38 _Vi: Can Clojure run on any alternative small JVMs?

18:38 ohpauleez: _Vi: such as...? The Blackberry VM?

18:39 _Vi: Tried "gij-4.4" as alternative JVM, it failed.

18:39 hiredman: yeah, no no

18:40 ohpauleez: ahh, really depends on the subset of instructions and lib support. But I would say most likely not

18:40 _Vi: Something like "java.lang.VerifyError: verification failed at PC 214 in ... incompatible type on stack"

18:40 hiredman: don't expect anything to work on the gnu java stuff

18:40 gcj, gij, etc

18:40 not a real jvm

18:41 _Vi: What else things it tested on apart from official Sun^WOracle JVM?

18:41 hiredman: blackberry uses j2me which is a striped down version of java 1.4 which nothing runs on

18:41 almost no phones have a decent jvm

18:42 _Vi: (Trying with some "jamvm-1.5.4" which is found by "Tiny JVM" request. Expecting a fail.)

18:42 hiredman: I've heard of clojure running on jam

18:42 but I think jam's gc is not so hot

18:45 _Vi: hiredman, Trying that.

19:06 bash$ ( ulimit -v 70000; jamvm -Xmx10m -jar clojure.jar) # works

19:08 hiredman: whats -v?

19:09 _Vi: Limit virtual memory to 70000 KB for jamvm.

19:09 amalloy: hey technomancy, who's in charge of slime/swank?

19:10 _Vi: Usual java requires over 200 MB.

19:12 tomoj: gcj worked fine for me doing relatively mundane things with clojure

19:12 I didn't even notice I had switched to gcj

19:38 _Vi: BTW I can checkpoint a jamvm process with cryopid, but can't do it with usual java. (However it does not increase starting speed of clojure anyway)

19:55 technomancy: amalloy: I'm in charge of swank-clojure, sorta. buncha CL guys are in charge of slime.

19:56 amalloy: technomancy: i can reliably crash emacs with swank-clojure, but can't easily reduce the problem to a few lines

19:58 technomancy: amalloy: must be a combination of Emacs and Slime bugs

19:58 never seen Emacs itself crash though; that's amazing

19:58 amalloy: i thought so too! it doesn't actually crash as in dump core, but it refuses to respond to anything or redraw the window or whatever

20:00 technomancy: oh, just a hang then. it could just be a slime bug then.

20:00 amalloy: but ugh, i seem to have fixed the problem without keeping around a copy of the clj file causing the problem

20:01 worst bug report ever

20:01 technomancy: it's OK, I'm not really in a position to fix elisp bugs anyway.

20:26 fbru02: what is a good way of composing lambda fns ??

20:29 wooby: fbru02: comp?

20:30 fbru02: wooby: i have yet try it out but the thing is i have fn1(z) and fn2(z) and i want fn3(z) = fn1(z) + fn2(z) what i mean is that i want them both to close over a particuar value

20:33 amalloy: ,(reduce + ((juxt inc dec) 10))

20:33 clojurebot: 20

20:34 amalloy: fbru02: (juxt inc dec) creates a new function that calls inc and dec on its arguments, and returns a list of the results

20:34 then i call that function on 10, yielding [11 9], and reduce it with + to get, effectively (+ (inc 10) (dec 10)), which sounds like what you want

20:39 fbru02: amalloy: wooby : thanks !!!

20:39 amalloy: a less trivial example, to add together 2n and n/2:

20:39 ,(reduce + ((juxt #(* % 2) #(/ % 2)) 10))

20:39 clojurebot: 25

21:27 _Vi: (def q (ref 0)), (def f (future (loop [] (dosync (ref-set q (+ 1 @q))) (recur)))), (dosync (for [x (range 1000)] @q))

21:28 Why it returns list where I see that q is updated? Isn't it in a transaction created by "dosync"?

21:52 Scriptor: what's the best solution for when you need to go through multiple lists at the same time?

21:52 not concurrently, say when you need to match each item in two lists

21:55 hiredman: ,(map vector (range 10 20) (range 30 40))

21:55 clojurebot: ([10 30] [11 31] [12 32] [13 33] [14 34] [15 35] [16 36] [17 37] [18 38] [19 39])

21:58 Scriptor: ah, so if map's given multiple lists, it does what I need?

21:59 Raynes: map applies the function to one element in each sequence that is passed to it until any one of the sequences are exhausted.

22:01 Scriptor: sounds good, do reduce and filter act in the same way?

22:08 Raynes: Scriptor: Nope.

Logging service provided by n01se.net