#clojure log - Dec 13 2009

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

0:16 quizme: http://clojure.org/runtime_polymorphism <--- seems like it can do everything OO can do

0:16 except inheritance?

0:18 harrison: you can use (derive ::child ::parent) for that

0:18 Licenser: also the article is about polymorphism not inheritance :)

0:22 http://clojure.org/multimethods <- is on multimethods and herachies

0:22 harrison: i'm getting this error when i try ant or ant jar: "[javac] javac: target release 1.5 conflicts with default source release 1.7" does that mean i can't use java 7, or is there a way to make it work?

0:23 Licenser: it looks to me like you are trying to run ant jar with a java 1.5 while the task says it wants 1.7

0:25 harrison: i just did a clean install of windows and put java 7 on it. it shouldn't even have older versions on it

0:26 i'll try it with java 6 and see if it works, i guess. that's what i have on my linux box, and it works fine there.

0:27 tomoj: the build.xml in clojure has target="1.5" in compile-java

0:27 I guess you could try changing that to 1.7.. :/

0:29 harrison: tomoj: seems to be working. thanks! (no error yet, anyway)

0:29 tomoj: hmm. does this mean 1.7 is not backwards-compatible with 1.5, but 1.6 is?

0:30 quizme: basically methods are not attached to objects.

0:30 Licenser: tomoj: 15 and 16 are not entirely compatible as well

0:30 I think at least

0:30 alexyk: how do I require c.c.duck-streams.with-out-writer without prefix?

0:30 Licenser: when I remember riht I had already the problem that it told me 'can't run this, it's made for 1.6 but you use 1.5'

0:31 harrison: Licenser: but you should never see "it's made for 1.5 but you use 1.6", right?

0:31 Licenser: no that should not happen and I don't think it will happen

0:31 w

0:31 what you see is the result of ANT not java

0:32 albino: use use not require ;)

0:32 alexyk: what I mean is, what's the import form after which I can use (with-out-writer ...)

0:32 Licenser: (use '[c.c.duck-streams :only (with-out-writer)])

0:32 I think that was the syntax

0:32 tomoj: or with a symbol and without the quote inside ns

0:33 (ns ... (:use [clojure.contrib.duck-streams ...

0:33 alexyk: Licenser: I wonder why some choose require, some do use?

0:33 tomoj: not a matter of personal preference :)

0:34 use is the one that pulls stuff into your namespace so you can use it with no prefix

0:35 Licenser: alexyk: use includes methods in your namespace, require only tells the VM to load the file so you could access the namesace

0:35 tomoj: require would be useful for instance if you wanted to say (duck-streams/with-out-writer ..)

0:35 alexyk: tomoj: you mean clojure-contrib.duck-streams/... ?

0:36 * alexyk typed dick-streams at first

0:36 Licenser: I used require when I had a few namespaces with the same functions in it soI could use a name space prefix

0:36 alexyk: you can 'alias' namespaces

0:36 tomoj: yeah, require's :as lets you give them a shorter name

0:37 that's pretty much all I've ever used, require :as and use :only

0:37 if you wanted to call it like (dick-streams/with-out-writer ..) you could do that too with require :)

0:38 Licenser: (require 'clojure-contrib.duck-streams :as 'dick-stream)

0:39 tomoj: need a vector around that I think

0:39 * Licenser never can remember where I need a vector a list or a quote :/

0:40 tomoj: I think whenever you're passing options that are specific to a particular namespace, you need to group them in a seq

0:40 and no quotes inside ns, otherwise...

0:40 Licenser: but it's the general spirt

0:42 tomoj: we can't nest libspecs, can we?

0:42 er, prefix lists I mean

0:43 * Licenser has no clue

0:44 * Licenser needs to go to bed so

0:44 Licenser: Rest well people!

0:44 tomoj: seems not

0:45 I think it might be kinda cool if you could, for big branchy libraries like compojure

0:46 (:use [compojure [server [jetty :only (jetty-server)]] [http [servlet :only (servlet)] routes]])

0:46 guess you don't save all that much typing :)

3:32 talios: Does anyone know of a way to pretty print clojure code from java? I was hoping clojure.lang.RT.doFormat() / .print() etc. might help but no :(

3:32 I guess it's time to hack up something nasty to start with then.

3:32 Carkh: have you tried using clojure.contrib.pprint ?

3:34 talios: For some reason I couldn't get that working from java. Keep geting "clojure.contrib.pprint/cl-format is unbound", after I RT.var() it.

3:34 then .invoke()

3:34 I suspect I was missing something simple there thou

3:35 Carkh: you need to (use 'c.c.pprint) first i think

3:35 talios: I think I might be best off manually doing this anyway, for what I'm wanting to do anyway ( code gen from java )

3:54 aluink: im trying to build a partial with a static method in java.lang.Math

3:55 this is what i'm thinking, but it doesn't work (partial (. java.lang.Math (max)) 1)

3:56 the idea would be to use it in a call to map or something, kinda like (map (partial (. java.lang.Math (max) 1)) [1,2,3,4])

3:56 _ato: aluink: java doesn't have first-class methods, they aren't objects, so you can't pass them around

3:56 ,(map #(Math/max % 3) [1 2 3 4])

3:56 clojurebot: (3 3 3 4)

3:56 aluink: hmmm, can i wrap one with a first class method?

3:56 _ato: ,(map max [1 2 3 4])

3:56 clojurebot: (1 2 3 4)

3:57 _ato: m

3:57 err

3:57 ,(map (partial max 3) [1 2 3 4])

3:57 clojurebot: (3 3 3 4)

3:57 _ato: I prefer the lambda syntax though

3:57 ,(map #(max % 3) [1 2 3 4])

3:57 clojurebot: (3 3 3 4)

3:57 hiredman: it's a function

3:58 aluink: i'm used to Haskell currying if you're at all familiar

3:58 hiredman: not a first class method

3:59 ,(pl (↕map (replicate 3 (↕apply vector $ (↕map range $ 10 inc · inc · inc) call · ⌽* $ 10 · call · (⌽+ -2) map)) shuffle)))

3:59 clojurebot: ((50 80 90 40 100 60 30 70 10 20) (60 100 30 80 20 40 90 70 10 50) (50 90 70 10 40 60 20 30 80 100))

3:59 _ato: I knew that was coming :p

3:59 hiredman: haskell?

3:59 clojurebot: haskell is Yo dawg, I heard you like Haskell, so I put a lazy thunk inside a lazy thunk so you don't have to compute while you don't compute.

4:00 aluink: say whaah?

4:01 hiredman: haskell like currying would be neat, but how do you curry functions like max that can take an infinite number of args

4:01 aluink: well, i was more thinking of currying functions from the java standard api that take a fixed number of args

4:02 i guess that gets tricky with overloading with multiple args

4:02 hiredman: those are not functions

4:02 they are methods

4:02 not first class values and attached to an object

4:03 aluink: hmm, i guess i have to learn the difference between class methods and fc fns

4:03 oh, sorry...fc methods

4:03 hiredman: aluink: their aren't first class methods outside of the Method objects you can get using reflection

4:03 there

4:04 some people just use "function" and "method" sloppily

4:04 aluink: whoop! over my head

4:05 * aluink is _very_ new to clojure and Lips in general

4:05 aluink: haha, Lisp*

4:05 hiredman: no one will know what you are talking about (except _ato) if you say first class method

4:06 because the only place such a thing could be said to exist is in the java reflection api, and no one calls them that

4:07 methods are not values, you can't pass them around, or put them in a collection

4:08 functions are values, and you can pass them as arguments to other functions, and put them in collections, and do all the things you can do with values with them

4:14 aluink: ok, now why doesn't this work? (defn m ([y] (max 2 y)))

4:15 (max n) always == n

4:16 hiredman: erm

4:16 the function you defined is bound to the name m

4:17 when you are doing a single arity function you would write it like (defn m [y] (max 2 y))

4:17 ,(doc max)

4:17 clojurebot: "([x] [x y] [x y & more]); Returns the greatest of the nums."

4:17 hiredman: if you pass max a single number, that single number is always the greatest number you passed

4:25 aluink: ,(defn m [x y] (max x y 3))

4:25 clojurebot: DENIED

4:26 hiredman: ,(let [m (fn [x y] (max x y 3))] (m 4 5))

4:26 clojurebot: 5

4:26 hiredman: ,(let [m (fn [x y] (max x y 3))] (m 30 5))

4:26 clojurebot: 30

4:26 aluink: iz'a learning

4:26 but needs sleep, thanks and night all!

4:31 Carkh: grmbl, crypto api not working the same on solaris ... gotta love that

4:45 LauJensen: When the profiler says that I'm spending all my time sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run() - Does anyone know what means? This is a trivial I/O heavy app which doesn't use network in any way

4:45 I/O as in Harddrive

4:47 Ah, I got tripped up by the time but I see now that its only 7 invocations, so its the instrumentation, nvm :)

6:28 Was spew or spit ever implemented for quickly dumping data to a text file ?

6:36 in contrib still I see

7:05 Can anybody think of an elegant way of transforming (["one" 1] ["two" 2] ["three" 3]) into one\t1\ntwo\t2\nthree\t3 - that is, interposing tabs and newlines ?

7:05 and by elegant I dont mean (apply str (interpose \newline (map #(apply str (interpose \tab %))) and so on

7:11 _ato: ,(str-join "\n" (map #(str-join "\t" %) [["one" 1]["two" 2]["three" 3]]))

7:11 clojurebot: "one\t1\ntwo\t2\nthree\t3"

7:12 LauJensen: ,(doc str-join)

7:12 clojurebot: "([separator sequence]); Returns a string of all elements in 'sequence', separated by 'separator'. Like Perl's 'join'."

7:12 _ato: in str-utils

7:13 LauJensen: ah ok, thanks

7:32 fliebel: what does it mean if the doc says "in linear time"?

7:32 LauJensen: O(n)

7:33 Meaning if the operation takes 1 sec for 1 item, then it takes 100 secs for 100 items

7:35 fliebel: thanks

7:41 A lazy seq is actually some magic function that returns only what is asked for, right? I'm trying to understand how they work, how I can fiddle with them and how I can make my own.

8:23 I'm staring at the lazy_seqs.clj source for a hint on what's actually happening. I understand that you can use iterate or map on a function that will return one part of the list at a time, and only need as much calls as items requested. but there is still some black magic going on there I don't understand.

8:24 chouser: each step of a lazy seq has a closure inside.

8:25 fliebel: uuuhm...

8:25 chouser: when you call 'first' or 'rest' or 'seq' on a lazy seq, it invokes the closure, expecting to get back a cons or nil. If it's nil, all those return nil.

8:26 If the closure returns a cons then that result is cached in that step of the lazy seq. Then 'first' returns 'first' of the cons, 'rest' returns 'rest', and 'seq' returns the whole cons.

8:27 fliebel: I can understand first… it just invokes the whole train once and… voila, the first value pops out.

8:27 chouser: not the whole train, just one step.

8:28 after invoking that first closure, you now have cached both the first value and a closure that represents all the rest (but hasn't been called yet)

8:28 ok, sorry, gotta run. good luck!

8:28 fliebel: thanks… :S

8:29 is there someone else to take over the story?

8:31 closures is just that you save the state of a scope for later, isn't it?

8:35 I should really work on my code understanding… It took me far to long to grasp 4 lines of code: http://lispwannabe.wordpress.com/2008/10/24/closures-in-clojure/

8:37 This confirms the way I was thinking about closures, but that does not explain to me how you can "invoke" a closure.

8:39 cypher23: fliebel, you don't, really. You invoke something that has a closure, like a function

8:41 fliebel: ah

8:41 now I got to run, I'll search on later...

10:04 LauJensen: I've blogged about how to implement a parallel newsgroup parser in 19 lines of Clojure, contrasting with Scala and Ruby: http://www.bestinclass.dk/index.php/2009/12/clojure-vs-ruby-scala-transient-newsgroups/

10:17 DeusExPikachu: what's the syntatic difference between a map entry and a map? I'm trying to figure out how to use val or key

10:23 the-kenny: DeusExPikachu: What do you mean with "difference between map entry and a map"?

10:24 DeusExPikachu: well, syntatically, I'm trying to use val, the doc says "returns the key of the map entry", I try putting a map in there, doesn't work, I try putting a vector of the key and value, doesn't work

10:24 I can't figure out to input a map entry

10:26 the-kenny: DeusExPikachu: I think val operates on a java-class and not the clojure equivalent

10:28 DeusExPikachu: If you want to get all values on a map, use vals

10:29 LauJensen: ,(class {:one 1 :two 2})

10:29 clojurebot: clojure.lang.PersistentArrayMap

10:29 LauJensen: ,(class (first {:one 1 :two 2}))

10:29 clojurebot: clojure.lang.MapEntry

10:29 LauJensen: ,(map val {:one 1 :two 2})

10:29 clojurebot: (1 2)

10:32 bagucode: LauJensen: Read the blog post. Good stuff.

10:33 LauJensen: bagucode: Thanks a lot

10:36 bagucode: Anyone here familiar with leiningen and ant? I'm trying to modify leiningens compile task to be able to set a directory for java.library.path and I think I got the correct path into a .addProperty on the ant java task but it does not seem to help. (Still get UnsatisfiedLinkError).

10:37 Here is my version of compile.clj http://github.com/bagucode/leiningen/blob/master/src/leiningen/compile.clj

10:49 DeusExPikachu: the-kenny, I'm trying to understand someone else's code so I just needed to understand the usage of val and key; LauJensen, so to confirm my understanding, a MapEntry can not be expressed without the help of a dereferencer (e.g. first, find) applied to a map?

10:50 LauJensen: you're asking if it has a constructor ?

10:53 DeusExPikachu: I'm asking if there's a first class like syntax for expressing a MapEntry like [] for vectors or {} for maps, "" for strings etc

10:54 LauJensen: Not that I know of. A MapEntry exists in a map only. At least thats my impression

10:55 DeusExPikachu: LauJensen, ok, thanks

10:59 tomoj: ,(map #(+ (key %) (val %)) {1 2, 3 4, 5 6})

10:59 clojurebot: (3 7 11)

11:16 Intertricity: Does anyone here play with ClojureCLR?

12:00 fliebel: LauJensen: Fun post :)

12:00 LauJensen: fun as in you liked it, or in many typos? :)

12:01 the-kenny: LauJensen: What's the url of your blog?

12:01 s/blog/blag/

12:01 LauJensen: http://www.bestinclass.dk/index.php/blog/

12:01 Thats the blog, I dont have a blag yet

12:02 Carkh: you're missing out, these are all the rage these days

12:03 fliebel: what is a blag?

12:03 the-kenny: http://www.xkcd.com/148/

12:03 rhickey: Clojure vs ____ posts hurt Clojure.

12:06 fliebel: rhickey: just the name, I think it's cool to compare two jobs done in different languages. Not necessarily for speed, but also for lines and readability.

12:06 tomoj: "Clojurian" :)

12:06 rhickey: They are antagonistic, they always misrepresent ____, they will never convince users of _____ anything since they have been put on the defensive, they encourage talk of fanboyism and erode people's opinion of the Clojure community

12:07 Intertricity: I was convinced of clojure a long time ago :3 but I'm only a python programmer, clojure will be my second language.. I get this feeling I should know like, C++ or Java before I enter

12:08 I've only done simple console based programs but I want clojure to become the language I'm fluent in :P

12:09 fliebel: rhickey: That is what I mean. It's mostly in the way those ___ vs ___ are represented I think.

12:12 Intertricity: I think ____ vs. ____ threads can be useful in finding what language does what better for specific purposes. But general ____ vs ___ threads I think, yes, are harmful.

12:13 fliebel: I agree with intertricity… I tend to look at a few of them to see if they fit my purpose and style and make my own decision. (i usually don't comment on them)

12:14 Intertricity: Moreover, it saves me the trouble of taking a month or two to learn it before I find that I hit a brick wall and have to go back to the drawing board.

12:15 fliebel: but still the best way to decide on anything is to compare the number of google results *sarcasm*

12:15 Intertricity: haha

12:16 ok I gotta do the fanboy thing a sec at rhickey- thankyou for making clojure :D I've been wanting a reason to learn lisp

12:16 rhickey: http://rosettacode.org/ is a neutral way to do comparative coding

12:16 Intertricity: you're welcome

12:16 Intertricity: :)

12:17 I'm currently trying to assemble the pieces to try out ClojureCLR. I have a .Net project I'd like to use to learn with.

12:18 LauJensen: rhickey: You've raised that concern before, but I must admit that after seeing you slam all OO languages with your Java keynote, your "Common Lisp leaves you high and dry" on Clojure.org, and your 3x comparison slam in that magazine interview, I must admit I found it to be a bit hypocritical

12:18 More so, there are several people that I've written with who are now trying out Clojure in response to comparisons

12:21 rhickey: LauJensen: your posts are full of value judgements, my JVM summit keynote made technical points about OO, time and values

12:24 LauJensen: where is the "Common Lisp leaves you high and dry"?

12:24 LauJensen: sec

12:24 rhickey: and what magazine article?

12:24 LauJensen: I was just trying to find the pdf. It was an interview you gave to Developers Journal or such

12:25 the-kenny: Yay... looks like forking swank-clojure on Github got stuck. No way to cancel :/

12:30 LauJensen: rhickey: In Clojure.org's rationale there used to be a phrase RE common Lisp which said 'left you high and dry in terms of datastructures', but that has been removed I see

12:32 "I think the Lisps prior to Clojure lead you towards a good path with functional programming and lists, only to leave you high and dry when it comes to the suite of data structures you need to write real programs"

12:32 Found here: http://en.wikibooks.org/wiki/Clojure_Programming/Tutorials_and_Tips

12:34 rhickey: LauJensen: so you trim the beginning and end off of that sentence and misconstrue it as a pot-shot? Gimme a break

12:35 I said the same thing (the entire idea of that sentence) right to the faces of the people who invented Lisp and Scheme and they didn't disagree

12:35 the non-list data structures of traditional Lisps are not functional

12:36 that's just a fact

12:37 LauJensen: I trimmed it to focus your attention on what I have referenced

12:37 Intertricity: Will ClojureCLR compile with VS 2008 express?

12:37 I only have a full version of 2005

12:38 LauJensen: bbl, you can accuse me of more things after dinner :)

12:42 Intertricity: Anybody know about the express 2008 compile?

12:43 scgilardi: Intertricity: I don't know for sure, but I believe the differences between the express versions and full versions have to do with things like source control integration and other "only needed by professionals" features. My guess is it would work fine.

12:44 Intertricity: scgilardi, ok thanks so much :)

13:31 Qvintvs: might anyone have any ideas as to why my swank repl has decided to stop evaluating code I type into it?

13:32 scgilardi: any chance you haven't yet supplied enough close-parens, close-braces, etc.?

13:50 Qvintvs: user> (def a 4) ... <enter> nothing, no new "user>" prompt. cursor just moves one line down.

13:51 the-kenny: Qvintvs: hm.. have you changed the mode or something? I'd try restarting the repl

13:52 Qvintvs: ive restarted it tons of times. (def a 4) was the first thing i typed in the repl.

13:52 scgilardi: does looking at your *inferior lisp* buffer give any clue?

13:54 Qvintvs: nothing as far as I can tell: http://pastie.org/741558

13:56 probably worth mentioning that i was playing around with sbcl in slime before, but i removed all traces of slime/swank i could find and completely reinstalled them

13:57 scgilardi: the inferior lisp looks good. it shows you're running clojure 1.0.0 (I assume that's what you intend). The repl in *inferior lisp* is "live". Is it true that Clojure does respond when you type there?

14:10 Qvintvs: sry, yes, it works there

14:15 alexyk: most comparisons of Clojure vs Scala, for example, are done by people who don't know at least one of those languages well. :)

14:15 qed: LauJensen: nice post on the newsgroups

14:16 alexyk: liebke: ping

14:16 LauJensen: qed: Thanks :)

14:16 qed: alexyk: while that's true, there are levels of "know"

14:17 if they are even intermediate level in both languages i think it's very telling of a language's strengths and weaknesses

14:17 you shouldnt have to be an uber advanced master of scala to write decent code

14:18 liebke: alexyk: what's up?

14:18 alexyk: qed: generally, a comparator is a fan of one of the languages and optimizes the heck out of it. Since he or she doesn't really know the other language, which he/she was turned off by, he/she takes a "to" code from a book, written hastily by an author who wanted to be the first to publish and is not a specialist on optimizing his language either. :)

14:18 liebke: I found that Mongo is the ideal back-end for Incanter!

14:18 any dataset goes right back via congomongo

14:18 liebke: really? sounds cool!

14:19 alexyk: say you compute a list of results, like pagerank. It's fed right back into Mongo and then can be visualized by incanter from another shell by easily reading it back and e.g. histogramming.

14:19 liebke: you should write something up, I'd love to see it

14:20 alexyk: liebke: it's really simple, I'll do a post on histogramming Twitter pagerank with incanter next week.

14:20 basically, I sense Incanter+Mongo is the R-killer. :)

14:20 liebke: excellent :-)

14:21 LauJensen: alexyk: Your right, I'm not a Scala Expert and I haven't tried to optimize the code, but I think I also state that in the conclusion, that its just for kicks and nothing too serious

14:21 liebke: hehe, I like R too much to kill it :-)

14:23 alexyk: LauJensen: I've tried to generalize,nice comparison for mechanisms demonstration, but numerically WideFinder in Scala from a year ago is still faster than all Clojure effort as of late, per twbray :) It's a risky business, comparisons...

14:23 liebke: did you try to interface Incanter to rJava?

14:23 LauJensen: And Tim Bray has now coded Clojure for how long, 3 weeks? :)

14:23 alexyk: LauJensen: he got code from technomancy and the John of Milo!

14:24 LauJensen: Ah ok

14:24 Well yes, comparisons are tricky

14:24 alexyk: LauJensen: generally he was advised on clojure much better than on Scala, and Scala does right next to Java there (from a year ago).

14:24 scgilardi: Qvintvs: sorry, I don't know what to suggest next.

14:25 LauJensen: alexyk: But I really cant trust any conclusion on Clojure performance which has not been through CGrand at least once :)

14:25 qed: ha

14:26 liebke: alexyk: no, I don't have any plans to interface with rJava at this time

14:27 alexyk: LauJensen: can you prod him to optimize wide finder? that would be awesome. twbray gives accounts to serious optimizers on his box. Then the race can be on again :)

14:27 liebke: I tried plotting in Mathematica via Clojuratica, too. X11 is much slower across the network, a no-go, but perhaps Export into a PDF may work.

14:27 LauJensen: I would be seriously surprised if cgrand couldn't bring Clojure up to par with Scala - cgrand you up for it?

14:28 alexyk: LauJensen: it appears it's still Sunday in France :)

14:29 LauJensen: oh thats right, snail time, nom nom nom :P

14:29 alexyk: LauJensen: with that Bordeaux :)

14:29 LauJensen: Where's the code of tbrays most recent attempt?

14:29 cgrand: red wine with snails... absolute nonsense

14:30 alexyk: LauJensen: the whole story is here: http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next

14:30 cgrand: that was intentional to cause outrage :)

14:30 LauJensen: <cgrand> I am so angry I could optimize the bytecode out of widefinder!!

14:31 alexyk: if you guys are up to it, I'll wake up Erik Engbrecht of Scala who did the last year submission to WF

14:31 that should be still on the box, porbably

14:32 cgrand: actually, I was thinking of revisiting WF2 before twbray started blogging about clojure. I hope I have time after xmas. Meanwhile I have too much on my plate

14:32 LauJensen: its your call cgrand, I can probably get it down to Scalas time, then you need to go beyond :)

14:33 cgrand: 18 months ago my best attempt ran in 16mins iirc (on the niagara box).

14:34 LauJensen: How long does Scala take?

14:34 And where's the link to his .clj file ?

14:35 alexyk: cgrand: that's almost at Scala/Java time, 14 mins iirc

14:35 qed: hahahahaha i just found M-x doctor in emacs

14:36 cgrand: alexyk: then i don't remember correctly

14:38 LauJensen: cgrand your last post states "So far my best runtime on the whole dataset is 27 minutes."

14:40 alexyk: LauJensen: yeah, that's what twbray reported, too.

14:40 cgrand: I haven't blogged about my subsequent gains because they were too ugly. 18 months later I'm (hopefully) wiser and have new toys (transients).

14:41 alexyk: cgrand: would be awesome to see!

14:42 LauJensen: Yea, if optimal Clojure is 27 and Scala is 14, I suggest we buy Rich a weekend retreat somewhere nice so he can reflect on the art of writing compilers :)

14:42 qed: careful, you're lible to get stabbed

14:43 Chousuke: :P

14:43 stuarthalloway: what do you think this should return: (flatten [1 2] nil [3 4])

14:43 hm, make that (flatten [[1 2] nil [3 4]])

14:45 alexyk: LauJensen: that's right, the ultimate shootout is between Rich and Martin Odersky -- then the retreat must be somewhere neutral, like Australia... :)

14:46 LauJensen: hehe

14:46 alexyk: but I've come to appreciate compactness of sexps and dynamic typing for data mining. It's not coincidental that R is also dynamic.

14:46 hence Incanter is a terrific idea for Clojure

14:47 ...and Mongo as its JSON, dynamic store

14:47 ...and Mathematica is very similar, hence Clojuratica.

14:49 LauJensen: J is the bomb though, for math stuff :)

14:49 alexyk: the main problem, I guess, it graceful handoff os heavy-duty stuff to computationally optimized engines, then getting it back.

14:49 LauJensen: average=. # % /+

14:49 doesn't get any better than that

14:49 Anyway, I gotta jet :)

14:52 fliebel: you know what would be really helpful? a "see also" section for functions in the api. so if you look at print it will tell you there is also println.

14:56 Drakeson: how should I use nailgun with clojure such that the context is also passed to the ns? (who should subclass NGContext? clojure or the ns?)

15:01 * the-kenny would like to see leiningen running with nailgun

15:02 alexyk: the-kenny: there's apparently a nailgun plugin, but I didn't try it yet

15:03 ~google "leiningen nailgun"

15:03 clojurebot: First, out of results is:

15:03 alexyk: http://clojars.org/lein-nailgun

15:04 * alexyk will bill clojurebot and hiredman

15:06 the-kenny: alexyk: If I look at the sourvce inside the .jar, it looks like the plugin only starts the server, not running leiningen with it

15:08 alexyk: the-kenny: that's too bad

15:09 ~google lein nailgun

15:09 clojurebot: First, out of 484 results is:

15:09 Re: combining vimclojure, classpaths and leiningen: msg#01039 clojure

15:09 http://osdir.com/ml/clojure/2009-11/msg01039.html

15:09 alexyk: ah, ok, so queries are not quoted.

15:15 digash: this does not look right to me (concat [-1] (range 5))

15:16 is this a best way to prepend element to the collection

15:16 stuarthalloway: digash: why not cons?

15:16 digash: does cons work with all coll?

15:18 stuarthalloway: ,(doc cons)

15:18 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

15:19 digash: ha, years of programming CL and I did not think of obvious cons, thank you

15:23 qed: oh man that's cool: (defn tally-map [coll] (reduce (fn [h n] (assoc h n (inc (or (h n) 0)))) {} coll))

15:43 chouser: ,({:a 1} :b 0)

15:43 clojurebot: 0

15:44 chouser: qed: so, (h n 0) instead of (or (h n) 0)

15:51 fliebel: I just finished writing my own prime number generator… it's about 10 lines of code. Can anyone have a look at it, to see if it's good and done "the Clojure way"? http://pastebin.com/m220ba365

15:55 Lol, for numbers below 100 or 1000 it's quite fast, but I'm still waiting for it to finish with 1000000 :D

15:55 Chousuke: fliebel: why do you sort m if you put them into a set right away?

15:56 also it'd be more idiomatic to use the set itself as the filter predicate

15:57 (filter #(not (contains? non %)) ...) is equal to (remove non ...) :)

15:58 (or (filter (complement non) ...))

15:58 fliebel: ok...

16:00 chousuke: what do you mean with the second thing?

16:00 Chousuke: I mean (filter (complement non) ...) is equal to (remove non ...)

16:01 fliebel: I meant before that… the idiomatic stuff.

16:01 Chousuke: ,(#{1 2 3} 3); sets are functions too

16:01 clojurebot: 3

16:01 Chousuke: ,(filter #{2 3} [1 2 3 4 5])

16:01 clojurebot: (2 3)

16:02 fliebel: huh...

16:02 Chousuke: ,(remove #{2 3} [1 2 3 3 4 1 2 5])

16:02 clojurebot: (1 4 1 5)

16:02 fliebel: wow....

16:02 works :)

16:03 I agree that looks better...

16:03 Chousuke: you need to use contains? if your set contains falses though :/

16:03 but that's not very common

16:03 fliebel: only numbers...

16:04 is there more I can improve?

16:04 Chousuke: ,(#{false} false); using a set as a function return the item, if it's in the set, so...

16:04 clojurebot: false

16:04 Chousuke: returns*

16:04 seths: wow, that's subtle

16:04 neat tho

16:05 Chousuke: often it's not a problem :)

16:06 fliebel: nil is the only thing besides false that evaluates to false isn't it?

16:07 Chousuke: as a boolean, yeah.

16:07 though you can construct objects of the Boolean class too

16:07 fliebel: hm

16:07 Chousuke: But you shouldn't.

16:08 use Boolean/TRUE and Boolean/FALSE if you need them :)

16:08 fliebel: what do you think of my prime thing as a whole? it's not very efficient is it?

16:09 Chousuke: I guess so :/

16:09 seths: does clojure contrib have a prime # generator?

16:09 fliebel: yes

16:10 Chousuke: I don't see anything really wrong with it though, so maybe it's just a slow algorithm?

16:10 fliebel: it's in lazy-seqs

16:10 Chousuke: except for the sorting, of course. I don't understand why you put that there :/

16:11 fliebel: chousuke: I removed it… It was for my testing, to make it easy to check the output for a human.

16:12 Chousuke: ah

16:12 if you wanted to make that more idiomatic the next step would probably be to remove the loop

16:12 fliebel: is a set the only thing you can call contains? on?

16:13 Chousuke: but I'm not sure which higher-order function is suitable :)

16:13 the loop might well be the easiest

16:13 fliebel: ah, like map and filter instead of recur?

16:13 Chousuke: or partition or iterate or whatever.

16:14 fliebel: how many of those are ther?

16:14 notallama: you can call contains? on maps (for keys) and vectors (for index)

16:14 Chousuke: fliebel: quite a lot

16:14 fliebel: and you can of course write new ones yourself

16:15 I'm not saying loops are always bad, but I think it's good exercise to solve problems without explicit looping :)

16:15 fliebel: chousuke: some more structure and help would be welcome in the api… It's one of the few things I like about PHP.

16:16 chousuke: like if you're looking at map it'll tell you that you can also look at filter, reduce, etc for similar behavior.

16:16 notallama: i generally treat loops as a code smell. they're not always bad, but they have the stench of premature optimization or not thinking the problem through enough.

16:16 Chousuke: yeah, well, the API doc is entirely generated from metadata right now, and the Clojure functions contain no cross-reference metadata

16:17 seths: the doc pages improved recently though, the urls are different

16:17 Chousuke: yeah. it's a work in progress.

16:17 seths: clojure.org points to github for docs now?

16:18 Chousuke: I think so

16:18 fliebel: chousuke: If I only knew those functions I'd love to contribute :D It's a kind of chicken-egg problem, you see...

16:18 Chousuke: If you want examples, reading core.clj itself is pretty good. Or contrib stuff.

16:18 there aren't that many functions :)

16:18 you can keep almost all of core.clj in your head.

16:19 fliebel: not at once I guess, having a good reference would ease the learning.

16:20 seths: I am trying to understand how (alter) works. It almost seems like it merges... (code follows)

16:20 ,(def lunchbox (ref { :snacks [], :healthy_food [] } ))

16:20 clojurebot: DENIED

16:20 seths: oh well

16:20 (dosync (alter lunchbox assoc :healthy_food ["apples"]))

16:20 (dosync (alter lunchbox assoc :snacks ["chips", "cookies"]))

16:20 notallama: fliebel: there's the cheat-sheet kicking around somewhere. also, it's handy to look at the sequences page on clojure.org

16:21 seths: the second call to alter (which would normally be inside the first's dosync?) makes no attempt to merge

16:21 but the apples are there afterwards

16:21 Chousuke: merge?

16:21 fliebel: notallama: The cheat sheet would be great! I read most of sequences and data_structures…

16:21 seths: ,(doc assoc)

16:21 clojurebot: "([map key val] [map key val & kvs]); assoc[iate]. When applied to a map, returns a new map of the same (hashed/sorted) type, that contains the mapping of key(s) to val(s). When applied to a vector, returns a new vector that contains val at index. Note - index must be <= (count vector)."

16:22 Chousuke: seths: of course. you altered the ref with the previous alter call

16:22 seths: so the next alter call uses the value which has the apples

16:22 refs are mutable, remember :)

16:22 seths: right

16:23 sorry, I was overcomplicating it in my head

16:23 Chousuke: yeah. it's pretty simple.

16:23 seths: lunchbox is derefed and then passed as the first argument to assoc?

16:23 dabd: hi I'm trying to start a Project REPL with netbeans's enclojure but it fails to start even though I have added clojure.jar and clojure-contrib.jar to the project. any ideas? thx

16:23 Chousuke: seths: something like that.

16:24 seths: thanks!

16:24 Chousuke: the key thing to remember is that assoc itself never mutates anything. it works with values.

16:25 and dosync, alter and refs handle the icky stuff

16:31 fliebel: (defn odd? [n] (not (even? n))) is the same as (def odd? (complement even?)) right?

16:58 the-kenny: Maybe I'm finally going to write a log-converter from Pidgin to Adium§

17:06 polypus: what's the simplest xml emitter lib for clojure.

17:06 ~ping

17:06 clojurebot: PONG!

17:29 tolstoy: polypus: prxml (clojure.contrib)

17:37 polypus: tolstoy: yep found it a minute ago, but ty

18:00 iM: hello

18:02 the-kenny: hi, iM

18:02 iM: oops

18:03 ssideris: wrong nick

18:15 polypus: what should i bind to *out* to get a string instead of printing to stdout?

18:15 tolstoy: with-out-str

18:15 Er, or something like that. It's in core.

18:15 polypus: tolstoy: thx again

18:16 tolstoy: I just did this stuff, using compojure for a resty thing.

18:47 j3ff86: i've been trying to find this in clojure book but didn't find an answer: what exactly does the ' macro do?

18:47 (quote)

18:48 tolstoy: prevents a symbol from being evalutated

18:48 j3ff86: ah, thanks

18:48 oh and what about the # sign?

18:48 tolstoy: Depends on context.

18:49 qed: #{}, #', #""

18:49 scgilardi: more detail here: http://clojure.org/reader

18:49 j3ff86: thanks

18:49 qed: if i have a route in compojure like (GET "/docs:entry" (example-entry (params :entry))

18:50 tolstoy: Also: http://java.ociweb.com/mark/clojure/article.html#Syntax

18:50 qed: how do i response to those params in an example-entry function

18:50 respond*

18:50 tolstoy: qed: You can just return a stirng, if you want.

18:51 qed: could you give me an example?

18:51 tolstoy: Or, (html [:h1 "hello"])

18:51 qed: like (defn example-entry [arg1] (html [:h1 :entry]))?

18:51 how do I use :entry

18:51 tolstoy: Hm.

18:52 (GET "/docs/:entry" (let [value (. request route-params :entry)] (html [:h1 value]))

18:52 Something like that.

18:52 qed: ah, thank you

18:53 tolstoy: You can also return other things, like a map: {:body "<h1>..." :content-type "text/xml"} I think.

18:53 qed: i wish there were more docs

18:53 i shouldnt probably even be using it without docs

18:53 tolstoy: http://groups.google.com/group/compojure/browse_thread/thread/3c507da23540da6e

18:54 Try that one. Seems to cover things pretty well, all told.

18:54 qed: cool ty

18:58 PrinceOfA: are there clojure equivalents for foldLeft and foldRight?

19:02 liebke: PrinceOfA: reduce is left fold

19:03 PrinceOfA: liebke: ok thx

19:03 i guess right fold would be reduce with reverse?

19:05 tomoj: not quite

19:06 you'd have to also wrap the function argument to switch the order of its arguments, I think

19:14 lghtng: is there much interest in RDF for Clojure, yet?

19:16 tomoj: ,(letfn [(foldr [fun val coll] (reduce #(fun %2 %1) val (reverse coll)))] (foldr cons nil '(1 2 3)))

19:16 clojurebot: (1 2 3)

19:22 * qed wipes sweat from his brow

19:22 qed: i cleaned up that ugly compojure tutorial doc

19:33 anyone want a proper copy?

19:33 w/ syntax hilighting and such

19:34 tomoj: qed: sure!

19:34 guess it's out of date some now, though, huh?

19:34 qed: yeah i believe so

19:34 do you think i should put it online?

19:34 it'd be easier that way for you to see the css and such

19:35 otherwise youll need that too :)

19:35 tomoj: is it just one file? gist?

19:36 qed: yeah i can do that too i guess

19:37 1sec

19:39 tomoj: I'm not sure how to proceed :/. on the one hand, clojure is beautiful, and I like compojure and enlive. on the other, erlang has webmachine which looks awesome, but as far as I can tell has nothing like enlive (and if it did, I think it would be ugly).

19:40 the-kenny: Google AppEngine would be perfect, if they would allow agents and such things.

19:40 tomoj: do they block you from making new threads?

19:41 the-kenny: tomoj: Something like this.

19:44 qed: tomoj: http://gist.github.com/255697 <--pygmentize.css

19:44 tomoj: http://gist.github.com/255696 --<compojure.html

19:47 http://qriva.org/compojure.html

19:50 the-kenny: tomoj: I've searched a bit and yes, you aren't allowed to create threads.

19:54 tomoj: qed: cool, thanks!

19:57 qed: np

20:11 tomoj: http://qriva.org/compojure.html it looks better now

20:11 i added a bit more css

20:11 okay, now that it's readable...

20:11 * qed reads

20:28 kunley: Hi!

20:29 I encountered some code a while ago which was supposed to generate js from some subset of Clojure. I don't remember if it was in contrib or some bigger project like compojure.

20:30 Can anyone give a clue where might it belong?

20:33 the-kenny: kunley: It's called scriptjure

20:33 It's on github

20:33 kunley: http://github.com/arohner/scriptjure/

20:34 kunley: Thanks. Incidentally, I just found it via HackerNews in a recent discussion.

20:36 Btw, the-kenny: thanks for your clojure-couchdb bugfix notice. I didn't have time to reply yet. I may merge our stuff when I get back to a project which actually uses Couch.

20:38 the-kenny: kunley: No problem :) I'm glad I can help.

20:41 tomoj: also clojurescript?

20:52 qed: any advice or documentation for doing a simple database with clojure?

20:52 like connecting to mysql

20:52 something along those lines

20:53 im open to other databases, just whatever has the most docs and is fairly easy to maneuver

20:54 the-kenny: qed: CouchDB is fairly easy in my opinion.

20:54 qed: right now im messing with clojureql

20:54 since it was nice and easy to plug into leiningen

20:54 the-kenny: If you have DB running somewhere, you can just start without any big setup-work like setting up tables.

20:54 qed: ah, that's nice

20:55 like sqlite sort of

20:55 the-kenny: which couchdb clojar do you recommend

20:55 there's ato's yours, evil-couchdb

20:56 the-kenny: qed: hm.. mine has some "big" modifications, like an argument to every function for the server. The other forks use a global binding *server*.

20:57 gilbertleung: hi everyone

20:57 the-kenny: qed: Clutch is nice to. You can write view-function (they are mostly equivalent to a query in sql) in clojure with it.

20:58 gilbertl: i'm using compojure and trying to figure out how to make the server instance log to a specific file

20:58 does anyone know how to do it ?

20:58 qed: the-kenny: could you give a use-case example?

20:58 like from the developer end i mean

20:59 gilbertl: no clue man, i cant tell you there's not a single mention of "log" in any of the compojure functions

21:00 the-kenny: qed: In couchDB, "queries" aren't created on the client, but on the server-side and are called views. A view is a javascript function which gets called for every document (like an entry in sql, but without a predefined structure), and can emit the data to the view (and modify the data with the commit a bit, but these modifications are only in the view, not in the datastore itself). With clutch, you

21:00 can write these functions in clojure.

21:01 But I've never tried clutch.

21:01 qed: ahhh cool

21:01 im not sure i even need a database at this point

21:31 tomoj: qed: I think the question is, what do you want to store, and what do you want to do to it?

23:08 hiredman: http://gist.github.com/255766

23:44 tolstoy: Anyone got a hint for compiling Clojure with ant? Gotta use it to fit in with some legacy. Is there a commmand line thing one can invoke from the jar to compile?

23:45 Hm. clojure.lang.compile, maybe.

23:47 hiredman: Compile

23:47 nbuduroi: Hi everybody

23:47 hiredman: you can looks at the build.xml that comes with clojure

23:47 tolstoy: clojure.lang.Compiler.compile, I guess.

23:47 hiredman: no!

23:47 tolstoy: hiredman: Ah, cool. I know I've seem something somewhere.

23:47 hiredman: clojure.lang.Compile

23:47 tolstoy: Okay.

23:48 nbuduroi: I just have a simple question about slime

23:49 is there a shortcut to make the repl go to the namespace of the file you're currently editing

Logging service provided by n01se.net