#clojure log - May 29 2010

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

0:26 timmorgan: loop/recur just about kicked my butt -- does it ever get natural?

0:26 ...to write, that is

0:27 replaca: yeah, I knocked out a couple in the last few days and it was pretty natural

0:27 timmorgan: ok, so there's hope

0:27 :-)

0:27 replaca: but also the more clojure you right, the less it seems you use loop recur

0:28 *write

0:28 argh :)

0:28 timmorgan: I see

0:29 replaca: map/filter/for, etc. all come to hand much quicker

0:30 timmorgan: and reduce? ...that's one I need to learn

0:32 I get the concept, but using it in real life seems difficult

0:44 * technomancy has a special place in his heart for reduce

1:00 timmorgan: why isn't there an any? function

1:00 testing for a non-empty vector, should I do (not (empty? vec))

1:01 technomancy: timmorgan: clojure inherited the unfortunately-named "some" function from CL instead of "any?". =(

1:01 fusss: any recent pointers on clojure + emacs?

1:01 tomoj: I think the standard idiom you're looking for might be (if (seq vec) ...)

1:01 but perhaps not

1:01 fusss: i have clojure-mode and swank-clojure alredy

1:01 technomancy: fusss: the latest swank-clojure readme should have you covered

1:01 timmorgan: ,(seq [])

1:01 clojurebot: nil

1:01 timmorgan: ,(seq [1])

1:01 clojurebot: (1)

1:01 timmorgan: ah yes!

2:33 defn: hello all

2:33 anyone do any jruby + clojure?

2:34 hamza: gents, am i wrong to understand that i can use protocols to add support for calls like conj pop etc for custom data structures?

2:40 bozhidar: defn: why would you need to combine them?

2:42 alexyk: JSON generators write things like "{\"9\":{\"jovenatheart\":1}}", how do I unquote field names' quote to write the raw string into a database?

2:44 tomoj: ,(println "\"9\"")

2:44 clojurebot: "9"

2:45 alexyk: tomoj: that doesn't unescape it

2:45 I mean the original

2:45 tomoj: I guess I have no clue what you're talking about

2:45 alexyk: so it does the right thing to print to screen, now I need to do the same into a value

2:46 tomoj: ,(seq "\"9\"")

2:46 clojurebot: (\" \9 \")

2:46 alexyk: tomoj: ah ok

2:47 tomoj: the string itself doesn't have backslashes in it, that's just the printed representation

2:47 defn: bozhidar: to have nice immutable stuff and the STM in jruby

2:47 tomoj: s/printed/whatever/

2:47 sexpbot: the string itself doesn't have backslashes in it, that's just the whatever representation

2:48 bozhidar: defn: why not just use clojure altogether?

2:48 defn: bozhidar: cause i can get away with it in a work project if i call clojure from jruby

2:49 bozhidar: defn: I guess you should just compile the clojure code and use it in the same manner you'd use it in a Java app, via JRuby's java interop

2:50 defn: bozhidar: yeah i suppose -- ive seen a few different approaches

2:50 one of them was basically just talking to a REPL

2:50 tomoj: talking to a repl sounds wrong

2:50 defn: agreed

2:50 which is why im asking :)

2:50 bozhidar: + 1 - and it's ineffective as well

4:54 maxhodak: is the current consensus that clojure is 'fast enough' or are there major efforts to speed it up right now?

4:55 tomoj: I believe the consensus is that you may sometimes have to do some work to get it fast enough in relatively small places, but don't take my word for it

4:57 I wonder why clojure isn't at http://wikis.sun.com/display/WideFinder/Results ?

4:58 maxhodak: tomoj: my experience has been that 90% of the time it doens't matter, and 7% of the time it matters you can make it fast enough with some work, but there's a wall

4:58 like, you aren't going to writing games in clj anytime soon

5:10 tomoj: I think clojure-mode should figure out which symbols are bound to functions in the buffer's namespace and color them appropriately

5:10 instead of relying on a static list

5:16 hoeck: tomoj: +1

5:17 tomoj: it just struck me that inconsistent coloring seems worse than no coloring at all

5:35 Chousuke: maxhodak: Clojure is generally considered fast enough but I don't think Rich has stopped coming up with ways to make it faster :)

6:45 naeu: has anyone else noticed that Clojure's byte behaviour is different in Clojure 1.2-SNAPSHOT compared with 1.1

6:45 Consider: (byte (bit-or (bit-shift-left 9 4) 1))

6:45 hoeck: naeu: yes

6:46 my workaround is to use (.byteValue 0xff)

6:46 naeu: How might I create a byte of 8 bits where the first 4 bits are 9 and the last four bits are 1

6:48 hoeck: ,(.byteValue 0x91)

6:48 clojurebot: -111

6:48 naeu: hoeck: hmmm, sure but it's not as descriptive as bit shifting

6:49 and I can't compose bytes using that method

6:49 I have a binary protocol where the first four bits are the message id and the next four bits are the params

6:50 and I was composing the full byte using bit-or and bit-shift-left

6:50 hoeck: ,(.byteValue (bit-or (bit-shift-left 9 4) 1))

6:50 clojurebot: -111

6:50 naeu: ah ok

6:51 do you have any understanding why we now have to drop into java interop to achieve something that was previously doable in pure clojure?

6:52 GeoffSK: emacs/clojure newbie - i have destroyed my binding to

6:52 "{"

6:52 - any suggestions how i fix the binding?

6:53 naeu: for example, the following looks strange: (byte-array 1 (.byteValue (bit-or (bit-shift-left 9 4) 1))))

6:53 hoeck: naeu: maybe to be consistent with int?

6:53 ,(int 0xffffffff)

6:53 clojurebot: java.lang.ExceptionInInitializerError

6:56 tomoj: perhaps in order to avoid accidental chopping


6:56 hoeck: btw, I would not consider calling a jdk objects method to not be "pure clojure", especially when it comes down to bit twiddeling

6:57 tomoj: "pure clojure" seems like a useless term to me unless it means "no java interop"

6:57 naeu: tomoj: sure, it just feels like .byteValue is a bit incongruous in that form

6:58 hoeck: GeoffSK: are you using paredit?

6:58 naeu: Perhaps this might be nicer: (byte-array 1 (byte-val (bit-or (bit-shift-left 9 4) 1))))

6:58 GeoffSK: hoeck: yes i am.

6:58 hoeck: GeoffSK: maybe: (define-key clojure-mode-map "{" 'paredit-open-curly)

6:58 GeoffSK: the err message is : Symbol's function definition is void: paredit-open-brace

6:59 hoeck: where do i put that?

7:00 hoeck: first try: m-x eval-expression

7:00 to test wether it works

7:00 tomoj: there is no paredit-open-brace for me

7:00 paredit-open-curly for { and paredit-open-bracket for [

7:00 naeu: GeoffSK: somewhere in your .emacs although you could try it out in your live emacs with m-x eval-expression (M-:)

7:00 hoeck: its for paredit 21 and above versions

7:00 or below

7:01 GeoffSK: sweet.

7:01 it worked.

7:01 naeu: GeoffSK: if you're new to emacs you might consider the emacs starter kit: http://github.com/technomancy/emacs-starter-kit

7:01 hoeck: then put that line in your init.el, after the (require 'clojure-mode) line

7:02 and after the (require 'paredit) line (if there is one)

7:02 GeoffSK: thanks hoeck that was a lifesaver

7:03 also thanks naeu.

7:04 naeu: GeoffSK: I totally recommend the starter kit. I learned so much from using it.

7:09 GeoffSK: hoeck: i am putting it in my .emacs file, but i get Symbol's value as variable is void: clojure-mode-map

7:14 tomoj: you could use the paredit-mode-map

7:14 the problem is that clojure-mode hasn't been loaded when you're trying to do the define-key

7:14 so the (require 'clojure-mode) line hoeck suggested will fix it too

7:15 GeoffSK: i am currently autoloading 'clojure-mode before the line i tried to add.

7:15 tomoj: autoloading?

7:15 GeoffSK: (autoload 'clojure-mode "clojure-mode" "A major mode for Clojure" t)

7:16 tomoj: yes

7:16 that doesn't actually load clojure-mode

7:16 GeoffSK: oh.

7:16 the paredit-mode-map variant worked fine

7:17 tomoj: the autoload will make the clojure-mode function available and on the first call it will load clojure-mode

7:17 GeoffSK: i see. that makes sense.

7:17 if i added a require then it would be loaded?

7:18 hoeck: yes

7:18 tomoj: but then your emacs startup would be more burdened

7:18 probably not noticeably so, I'd hope

7:18 but the more stuff you require at startup, the longer it will take

7:18 GeoffSK: i only use emacs for clojure anyway

7:20 tomoj: for now :P

7:20 GeoffSK: i know, i have started down a dark path

7:20 appreciate the help.

7:21 on a different matter, has anyone read the "Practical Clojure" book ?

9:11 tomoj: is it good form to name your protocols like IFoo ?

9:11 Raynes: I hope not.

9:11 tomoj: I thought I had seen that somewhere

9:11 so, I mean, hmm

9:12 you end up taking good names out of people's vocabulary

9:12 chouser: tomoj: That's somewhat normal for interfaces. I don't think a protocol naming style has been settled on yet.

9:12 tomoj: I mean, if you have a User protocol, what do developers call their implementation of it?

9:12 maybe I will use something like <Foo>

9:12 seems crazy

9:13 chouser: I think hiredman has recommended <Foo>, but I doubt it'll catch on.

9:13 tomoj: I liked it when hiredman was recommending <foo> for defstruct

9:13 I think I'll join his doomed campaign

9:13 chouser: Clojure has some interfaces named like adjectives. Sequable, Counted.

9:13 tomoj: the only official protocol I know of is InternalReduce

9:13 chouser: oh, maybe it was structs I was thinking of

9:15 tomoj: the docstring for defprotocol sounds like a rapid list of awesomeness

9:35 do you think it's true that defprotocol, defrecord, deftype allow shallower trees of inheritance than java stuff?

9:36 I mean, when you hit a class, you can't inherit any further, right?

9:39 hmm, you can't have two protocols in the same namespace which share a method name, huh?

9:48 Chousuke: tomoj: they're protocol *functions*. They work just like a normal function

9:49 tomoj: yeah

9:59 chouser: tomoj: yes, shallower.

10:02 Raynes: Whoa. I need sleep. I had to read that 5 times to realize that chouser wasn't calling tomoj a "swallower". :<

10:02 * Raynes goes to sleep.

10:05 dmiller2718: rhickey: I rewrote the ClojureCLR wiki entry regarding proposed extensions to deftype and friends, to make it clearer what I think is necessary and what is optional. Whenever you have chance.

10:47 alexyk: lancepantz: ping

11:22 Moominpapa: This is going to sound like an odd question, but has anyone ever encountered "Invalid token d:"

11:23 The curious thing is, I'm getting it from trying to run leiningen repl. "D:" is my drive name (I'm on Windows) but I've carefully removed it from my path.

11:23 ^^classpath

11:24 Exact and incredibly ugly command is

11:24 java "-Xbootclasspath/a:..\leiningen\lib\clojure-1.2.0-master-20100528.120302-79.jar" -cp "test;..\leiningen\leiningen-standalone.jar;lib\ant-1.6.5.jar;lib\classworlds-1.1-alpha-2.jar;lib\clojure-1.2.0-master-20100528.120302-79.jar;lib\clojure-contrib-1.2.0-20100528.120551-119.jar;lib\jline-0.9.94.jar;lib\jtidy-4aug2000r7-dev.jar;lib\junit-3.8.1.jar;lib\maven-ant-tasks-2.0.10.jar;lib\maven-artifact-2.0.10.jar;lib\maven-artifact-manager-

11:28 mefesto: Moominpapa: could you pastebin that, it looks like it was cut off

11:29 Moominpapa: http://pastebin.com/VP8BD48q

11:33 Just edited it. The following does it too

11:33 java "-Xbootclasspath/a:..\leiningen\lib\clojure-1.2.0-master-20100528.120302-79.jar" -cp "test;..\leiningen\leiningen-standalone.jar" clojure.main -e """(use 'leiningen.core) (-main 'repl)"""

11:34 Where leiningen standalone is an uberjar compilation from trunk.

11:34 Don't know if that matters.

12:12 patrkris: conj is O(1) on both persistent lists, vectors and maps?

12:14 chouser: It's always nearly O(1) or actually O(1), yes.

12:17 conj, I mean.

12:18 patrkris: when it is not actually O(1), what is it then?

12:18 nevermind, i'll just write "near-constant time"

12:19 chouser: yes

12:19 oh, I lied.

12:19 conj on a sorted map or set if O(log2 n)

12:20 conj on a vector is O(1)

12:20 wait, someone made a nice chart...

12:25 Chousuke: chouser: I did, but I forget where it was posted :P

12:26 chouser: http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html

12:27 Chousuke: huh, that table looks a bit weird in my browser

12:28 the titles are shifted to the left by one :/

12:28 chouser: it's really a solid chart.

12:28 oh. hm

12:28 I don't like to use 'head' or 'tail' -- their meaning seems vague and/or hard to remember for me.

12:37 patrkris: chouser: thanks for the chart

12:37 or Chousuke, I should say :)

12:39 pdk: which chart is this

12:39 for the rest of us who may also make use of it :p

12:39 chouser: pdk: http://www.innoq.com/blog/st/2010/04/clojure_performance_guarantees.html

13:00 Ankou: hi, I'm getting the error "Exception in thread "main" java.lang.Exception: The syntax for defmulti has changed. Example: (defmulti name dispatch-fn :default dispatch-value) (tile_helper.clj:4)" but in line 4 of tile_helper is just the ns form just like everything else in the stack trace which belongs to my code is the first line of some ns form. I have no idea how to search for such an error so maybe you can help me?

13:07 arkrost: hI! For example, I can do (def do println) ((var do) "example") and it will work correct. How to do the same in let binding. I mean (let [do println] ...)

13:33 hI! For example, I can do (def do println) ((var do) "example") and it will work correct. How to do the same in let binding. I mean (let [do println] ...)

14:15 hoeck: arkrost: `do' is a special symbol, so you may not be able to define a new binding for it with `let', because its treated specially by the reader and or compiler

14:17 Ankou: currently, the only way is to either search in the tile_helper.clj (or all required/used files) for malformed defmulti expressions

14:18 Ankou: or put println statements somewhere in the file to see until which statement the file loads correctly

14:18 Ankou: or require the namespaces tile_helper.clj requires in its ns declaration on the repl to see which namespace actually causes the exception

15:00 seoushi: so I'm new to clojure and have limited experiance with lisps in general I was wondering if anyone would be interested in looking over some code of mine and giving general pointers http://github.com/seoushi/8-bit-game/tree/master/src/com/seoushi/

15:32 arohner: is there a way to detect when you're using slow math?

15:32 aside from using a profiler

15:33 visualVM takes 30 mins to start profiling my app, and once started, I can't reload classes

16:02 it appears there's no clojure.lang.Numbers.divide(int, int), but there's (int,float) and (int,double)

16:02 anyone know why?

16:03 seoushi: I've just been using the normal divide and then flooring it for integer math

16:03 arohner: seoushi: I'm looking for the performance of primitive math. having no (int,int) means I get a reflection warning

16:04 seoushi: arohner, ah yeah. at this point in time I'm not optimizing anything (still learning)

16:05 I haven't found anything built in for modulo yet tho

16:09 arohner: ,(doc mod)

16:09 clojurebot: "([num div]); Modulus of num and div. Truncates toward negative infinity."

16:10 seoushi: hmm I swear I tried that

16:12 looks like enclojure by default installs clojure 1.0.. time to update

18:51 herdrick: so, what's the current way to do performance profiling in Clojure?

18:58 riddochc: herdrick: I suspect any java profiler would work, but there's also some handy functions in contrib...

18:59 Joreji: Hey guys, is there some way to figure out which clojure functions/methods/macros are being called in an application and deploy the application compiled AOT with only those functions/methods/macros?

19:00 herdrick: riddochc: ah, in clojure.contrib.profile Those look pretty cool. Thanks.

19:14 riddochc: Here's a handy function I wrote, which has been quite useful so far: http://paste.lisp.org/display/110958

19:14 tomoj: nifty

19:15 that seems like it would make a common faq easy

19:15 er, hmm, not quite

19:21 chouser: aravind: did you figure out what you wanted to about primitive math?

19:22 erm, sorry, wrong nick

19:23 riddochc: tomoj: Which FAQ?

19:24 tomoj: (foo {:a 1 :b 2} {:a 3 :b 4 :c 5}) -> {:a [1 3] :b [2 4] :c [5]}

19:25 but assoc-or-addto is not quite right for it it seems

19:26 riddochc: Oh, not really. It's related, though. It's more like assoc than it is like merge-with.

19:27 tomoj: well, I was thinking it could be the f for merge-with, but nope

19:27 some piece of the code for assoc-or-addto would work as the f for merge-with, I think

19:27 but then there's also the problem where only one values is given for a key, hmm

19:27 I don't even remember a nice solution to that problem

19:28 chouser: ,(reduce (fn [m [k v]] (assoc m k (conj (m k []) v))) {} (concat {:a 1 :b 2} {:a 3 :b 4 :c 5}))

19:28 clojurebot: {:c [5], :b [2 4], :a [1 3]}

19:29 * chouser goes to mow the lawn

19:31 tomoj: ah, (m k []), neat

19:32 riddochc: Reduce is great. Once again.

19:55 zakwilson: http://gist.github.com/418631 <-- I'm having some trouble wringing performance out of a quad-core machine. Would someone care to try this code on a 4+ core machine and compare results?

19:56 It seems like this should be absurdly parallel, but I'm barely getting any speedup when involving more than two cores.

19:59 tomoj: hmm

19:59 (apply concat (pmap ...))

19:59 is that OK?

20:00 pmap is "Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required"

20:02 mitkok: Hey, guys. Anyone using vimclojure. I've got problem running the ng-server. It gives me : Exception in thread "main" java.lang.NoClassDefFoundError: com/martiansoftware/naulgun/NGServer

20:03 zakwilson: tomoj: I'm pretty sure it is. Wrapping the pmap in a doall just slowed it down slightly.

20:04 Actually... that's probably within the margin of error.

20:04 Ankou: is there a reason why it is forbidden to use a namespace with a definition which is also in the current namespace instead of just let the current namespaces definitions shadow the deifnitions of the used namespaces?

20:05 zakwilson: In any case, it sustains 390% CPU usage for the vast majority of its runtime.

20:08 tomoj: ah

20:08 I wonder how the pmap decides what to consume

20:08 (apply concat ...) seems like it would only force the evaluation of one result at a time

20:09 but it clearly doesn't, then

20:09 zakwilson: It appears to force the whole thing.

20:09 tomoj: I guess I don't know what "semi-lazy" means, then

20:09 it races a bit ahead of the consumers or something?

20:10 zakwilson: Something like that.

20:10 If you don't consume anything, it doesn't produce anything. That much, I'm sure about.

20:10 riddochc: Hmm.

20:10 ,(let [q (fn [&a] (coll? a))] (q "foo"))

20:10 clojurebot: java.lang.Exception: Unable to resolve symbol: a in this context

20:10 riddochc: ,(let [q (fn [& a] (coll? a))] (q "foo"))

20:10 clojurebot: true

20:10 zakwilson: (do (pmap some-slow-f some-seq) nil) ;returns almost instantly

20:11 riddochc: Evidently, whitespace matters.

20:12 zakwilson: The real world requires my attention at the moment. I'll make a google group post about this later, as I'd really like to get this machine running on all four cylinders.

20:12 tomoj: ,'&a

20:12 clojurebot: &a

20:13 tomoj: ,(let [foo 3 bar 4] foo)

20:13 clojurebot: 3

20:13 tomoj: ,(let [foo3bar 4] foo)

20:13 clojurebot: java.lang.Exception: Unable to resolve symbol: foo in this context

20:13 tomoj: yes, whitespace matters..

20:13 zakwilson: ,(let [&a "foo"] &a)

20:13 clojurebot: "foo"

20:13 zakwilson: & is a valid part of a symbol name

20:13 so are numbers

20:13 ,(let [foo3bar 4] foo3bar)

20:13 clojurebot: 4

20:14 tomoj: ,(let[foo3]foo)

20:14 clojurebot: java.lang.IllegalArgumentException: let requires an even number of forms in binding vector

20:14 tomoj: what I mean to say is that I don't think it should be surprising that whitespace matters :)

20:18 riddochc: Well, no, it's not surprising, I just hadn't expected & to be a valid character in a symbol.

20:19 Took me a while to figure out why a (defn ... [... &rest] ...) wasn't working.

20:30 tomoj: ah, yeah

20:30 there are many valid symbols which surprise me

20:30 ,'foo:bar

20:30 clojurebot: foo:bar

20:30 tomoj: ,'<3

20:30 clojurebot: <3

20:34 riddochc: Hm. Having some difficulty with [... & rest] args, anyway.

20:38 DeusExPikachu: is there a repl-utils that runs with no errors for clojure-1.2.0?

20:43 nm

21:27 riddochc: Hm. I guess I expected compojure's routing abilities to be a little less... minimalistic.

21:34 * riddochc considers ditching routes, and using a multimethod, something like handle-request.

21:35 tomoj: riddochc: clout?

21:36 there's also moustache, which I find deliciously minimalistic

21:37 hmm, a multimethod would be cool, but the dispatch function will be the same always

21:37 so how do you make it extensible?

21:38 riddochc: tomoj: Looks like compojure uses clout anyway.

21:38 tomoj: yeah, that's what I meant

21:39 is clout much different than old compojure?

21:39 riddochc: I'm not sure.

21:39 tomoj: what's wrong with minimalism? I mean, what features are missing?

21:39 I'm not saying there aren't any, just wondering what they are

21:41 riddochc: Well, I'm having a hard time getting it to handle something like /history/:version/:page

21:41 tomoj: ah, interesting

21:42 riddochc: Though the test for keyword-paths suggests that it should work...

21:43 tomoj: in moustache I believe it'd be: (app ["history" version page] my-handler)

21:48 riddochc: Looks like it's time for me to read some code...

23:48 trptcolin: i'm noticing some interesting behavior with clojure.test/are - http://gist.github.com/418759

23:51 tomoj: that's not how to use are

23:51 oh, sure it is

23:51 trptcolin: anyone have any insight into why do-template seems to work this way? (replacing bindings in both the template expression AND the template values)

23:52 so it works fine if i use z in my function - but the template variable x binds everywhere it occurs in the values in that first example

23:54 maybe the solution is just not to write anonymous functions inside are, or just being careful with argument naming...

23:55 tomoj: is it a do-template bug?

23:55 #(* % %) would work here too, but, not really a solution

23:55 trptcolin: it feels like it to me, but i'm not savvy enough about what do-template does

23:56 i get close to what i wanted by patching do-template to return (walk/postwalk-replace (zipmap argv values) expr))

23:56 instead of (walk/prewalk-replace (zipmap argv values) expr))

23:57 that is, then "are" works as i expect.

23:59 however, adding a test case to that effect gives me: http://gist.github.com/418767

23:59 which kind of baffles me

Logging service provided by n01se.net