#clojure log - Aug 25 2009

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

0:59 lowlycoder: anyone got experience with clojure on hadoop?

0:59 make that clojure / hadoop / ec2 :-)

1:20 tomoj: lowlycoder: I saw some code someone had written somewhere

1:20 maybe on the group

1:20 http://github.com/stuartsierra/clojure-hadoop

1:22 lowlycoder: that name looks familiar from googling around

1:22 i had imagined this would be a bigger deal somehow :-)

1:22 you know, after learning clojure; it's a lot less impressive than I thought it would be

1:22 there's some minor changes, but no mind blowing magic

1:34 rathore: lowlycoder: in what sense?

1:41 tomoj: maybe the persistent collections aren't mind blowing, but they're still awesome

1:43 JAS415: mindblowing

1:44 i feel like lispers always explain lisp as if its mindblowing, but really its not mindblowing on the surface, its kind of mindblowing after 3-6 months of hacking it

1:44 clojurebot: "if you never learnt Lisp, then you never learned to program" -- some rant on some blog somewhere

1:44 JAS415: like you can come to clojure or CL and treat it like c or python and kind of go 'meh' and not be that impressed

1:46 tomoj: homoiconicity blew my mind

1:47 JAS415: yeah that's the mindblowing part

1:47 although i guess the mindblowing part is what you can do with it

1:47 not so much the homiconicity itself

1:48 dosync: for me it was lazy sequences.

1:48 tomoj: code that writes code is just plain awesome. I love recursive/self-referential stuff like that

1:48 oh yeah, I remember having my mind blown when I created a sequence of all the integers

1:50 dosync: i am pretty sure the STM will blow my mind away too, once i grok its possibilities. For now, "snapshot isolation" just seems like something that is nice to have. :)

1:51 Look at this post for eg. http://groups.google.com/group/comp.lang.lisp/msg/a86c91091ae16970

2:50 tomoj: I can't seem to get ns syntax right

2:50 (use (clojure.contrib.pprint :only [:cl-format]))

2:50 what's wrong?

2:52 hiredman: :use and

2:55 mikem`_: should it be (use '[clojure.contrib.pprint :only [cl-format]])

2:55 tomoj: it's in ns, so no quoting necessary I think

2:55 oh, the error I'm getting now is that cl-format is not public

2:55 that's odd

2:56 mikem`_: tomoj: ah, you're right :) as hiredman says, you need :use, though

2:56 tomoj: got that

2:56 now this illegal access error, hmm

2:56 cl-format is clearly public

2:57 if I (use 'clojure.contrib.pprint) at the repl, I can use cl-format

2:57 but (:use [clojure.contrib.pprint :only [:cl-format]]) in ns won't compile

2:57 dosync: no : before cl-format

2:58 tomoj: oh, d'oh

2:58 thanks

3:00 Raynes: I just spent 20 minutes trying to figure out why I couldn't use anything from clojure-contrib, before I realized that I never built it. :|

3:00 /fail

3:25 LauJensen: Top of the morning gents

3:26 cgrand: moin

3:27 LauJensen: cgrand: tres bon, si'l voi plait, qui qui madam

3:29 gko: tu vas bien ?

3:36 dcooper8: git clone git://github.com/kevinoneill/clojure-contrib.git

3:36 does not seem to work

3:37 is there a "standard" location for clojure-contrib?

3:37 hiredman: yes

3:37 ~contrib

3:37 clojurebot: contrib is http://github.com/richhickey/clojure-contrib/tree/master

3:37 hiredman: the kevinoneill repos were unofficial github mirrors when clojure was using svn

3:38 dcooper8: that is from http://riddell.us/tutorial/clojure/clojure.html

3:39 hiredman: then it's old

3:46 dcooper8: should i be able to:git clone

3:46 git clone http://github.com/richhickey/clojure-contrib/tree/master

3:46 ?

3:46 if i try that, i'm getting a corrupted file error

3:47 hiredman: git clone git://github.com/richhickey/clojure-contrib.git

3:53 dcooper8: thanks, got it.

6:14 alinp: hi

6:14 what's the best way to add an element to end of a sequence ?

6:15 I'm missing something about cons/conj since it adds the element as the 1st in the given coll

6:15 clojurebot: (conj {:a 1} (when true {:b 2}))

6:15 liwp: it depends on the collections type

6:16 if the collection is a list, the new element will be added to the front since that's an O(1) operation

6:16 alinp: ok .. so how can I add it to the end ?

6:16 if the coll is a list

6:17 liwp: you really shouldn't since it's an O(n) operation

6:17 can you use vectors instead of lists?

6:17 with a vector conj adds the element to the end

6:17 alinp: yeah, I think so

6:18 liwp: ,(conj [1] 2)

6:18 clojurebot: [1 2]

6:18 liwp: ,(conj '(1) 2)

6:18 alinp: ,(conj [2 3 4] 1)

6:18 clojurebot: (2 1)

6:18 alinp: yeah

6:18 clojurebot: [2 3 4 1]

6:18 alinp: thanks

6:18 liwp: no worries

6:19 Neronus: quick to write and not so efficient if you want to stay with lists: (reverse (conj (reverse list) x))

6:19 liwp: if you really want to deal with lists a common idiom is to build the list back-to-front and then reverse the list before returning it

6:20 so you get o(1) adds and then a single O(n) reverse

6:25 Neronus: http://paste.lisp.org/display/86002 Something like that

6:25 but I don't think that that is more efficient than my solution above

6:26 liwp: Neronus: yeah, it's basically the same thing, i.e. iterate through the list, conj an element, and reverse it

6:27 so in general it's just a bad idea to use lists if you need to append to the collection

6:29 Neronus: yeah. Great for using them as stacks, though. Can be used for queues to (i.e. add last), but this isn't that easy

6:30 na, sorry, the last one is only true when using modifiable cons cells

6:30 btw, a short benchmark shows, that the version I pasted is a little faster (about 50 msecs on my PC)

6:31 liwp: Neronus: there's a cool functional queue by Chris Okasaki which is also the basis of the PersistentQueue in Clojure

6:31 basically you have a pair of lists, you conj to the second list in order to append to the queue

6:31 you dequeue by taking the head of the first queue

6:32 first list even

6:33 and when the first list is empty when doing a dequeue you take the second list, reverse it, and create a new pair with the reversed list and a new empty list

6:33 if that makes any sense ;)

6:34 Neronus: It isn't slower if I modify clojure.core/reverse to use loop/recur instead of reduce

6:34 liwp: your benchmark?

6:35 how long is you list in the test?

6:35 Neronus: I defined a list of a million zeroes and added a one to the end

6:35 liwp: hmmm

6:36 AFAICT (reduce) calls into the Java reduce function that the PersistentList implements, so you'd expect the reduce implementation to be faster...

6:36 so how long does it take to add an element to a 1M element list?

6:41 Neronus: liwp: reduce calls a java reduce function for chunked sequences, and list aren't chunked. If the collection isn't chunked, it uses loop/recur

6:42 About 600 msecs for me

6:42 liwp: oh, ok

6:43 oh yeah, that's right

6:46 Neronus: do you use slime?

6:46 Neronus: liwp: Yupp

6:46 liwp: how do you fix your repl after you've printed 1M integers in it and it's abysmally slow? ;-)

6:46 I'm assuming it's the size of the buffer that's causing problems

6:47 since my irc buffer is fine

6:47 Neronus: liwp: I restart the repl

6:47 that is, I close the buffer

6:47 liwp: yeah, that's what I've done in the past. There should be a better way though...

6:48 that's better!

7:13 Licenser: I like the 'what you're doing wrong' part of the video

7:19 tomoj: liwp: M-x slime-repl-clear-buffer

7:19 liwp: which for me is C-c M-o

8:07 raphinou: I've posted about my use of clojure with Jwt at: http://www.nsa.be/index.php/eng/Blog/Using-Jwt-yes-it-s-a-J-with-Clojure

8:08 For those who were here the last days, it's for this post that I had problems implementing 2 nested interfaces having the same name ;-)

8:08 feddback welcome

8:10 liwp: tomoj: thanks! I'll try that the next time I do something stupid

8:17 AWizzArd: Hello rhickey. Do you accept Contributor Agreements also when they are sent via fax?

8:18 rhickey: AWizzArd: not so far, no

8:19 fsm: Hi AWizzArd

8:20 I made some changes to my project according to your suggestions from a while ago

8:20 AWizzArd: Ah, hi fsm, I got your message and already looked at your code. It is really nice.

8:20 And hard to believe btw that you are a raytracing newbi...

8:22 fsm: Still plenty of room for improvement, but in that field there is infinite room for improvement.

8:23 Now, I search for some kind of trick to eliminate nested if statements

8:23 cark: fsm : have you tried taking advantage of the easy parallelism of clojure to speed up rendering ?

8:23 fsm: I have several algorithms that depend on exiting as early as possible for speed, which makes nested code

8:23 cark: yes, it was possible to make it multi-threaded with about 8 lines of code

8:24 cark: hehe nice =)

8:24 fsm: i am using atoms, i think if i changed to pmap most of that would go away (?)

8:24 cark: atoms ?

8:24 oh

8:24 fsm: agents*

8:25 cark: i don't know, agents are very often the way to go, i don't have time to dig in your code togive pertinent advice

8:25 fsm: it was really a matter of adding 'start' and 'end' co-ordinates to my rendering function, a minor change

8:26 but now, i wish for some kind of 'lazy let' so that variables are only computed if they are referenced

8:26 cark: as for the nested if thing, you might want to look into the maybe monad, though that will make a lot of function calls (slow)

8:27 fsm: yes, i think that is what i was looking at in haskell

8:27 the problem is, I have millions of tiny operations, that are easily overwhelmed by a little overhead

8:27 but that is why people write these things in C

8:27 cark: or you could make some kind of macro for that...

8:28 fsm: i am going to look at the maybe stuff, the code might become slower, but i might learn something.

8:29 the promise of having code that describes the problem rather than the solution is very interesting

8:29 Neronus: fsm: Are the many nested ifs in one function? I guess you know about cond? If this isn't the solution, then I don't understand the problem

8:30 cark: cond exits as soon as it reaches a true condition

8:30 fsm: The problem is, I may have e.g. 8 variables in a function, which are moderately expensive to calculate. After calculating the 2nd, 4th, and 6th (for example) i test the results so far and see if i can exit, to boost speed

8:30 Neronus: btw: is that your raytracer http://code.google.com/p/cray/?

8:30 fsm: yes, that's it

8:30 Neronus: nice :)

8:30 fsm: thanks

8:31 I didn't code in any lisp type languages before, so the code is a little rough... but it is getting better.

8:32 tomoj: hrmm

8:32 fsm: anyway, right now i have to do 3 levels of nested if and let, for those type of routines

8:32 Neronus: fsm: What about delay and force? wouldn't lazy variables help?

8:32 tomoj: ah, delay and force look cool

8:33 fsm: that looks interesting, there are plenty of things I don't know about that are already there

8:33 tomoj: you could write a lazy-let that replaces all instances of the symbols in the body with (force <the-symbol>) and puts delay around the bindings, right?

8:34 though that means every access to those variables is a function call :(

8:34 fsm: for now, i have wrapped some of my calculations in anonymous functions, that kind-of gives me what i want (cuts down on nesting)

8:34 but the cost is another function call, so it is only good for expensive calculations

8:34 Chousuke: you could perhaps write some kind of an extension to let like (something [a (foo) b (bar) {:guard (= a b) :or value-if-guard-fails} c (more a b)] ...)

8:35 fsm: interesting, that kind of thing is a good way to go up a gear in learning

8:36 Chousuke: remember, macros let you have any kind of syntax for anything you want, as long as its made of clojure data structures. :)

8:37 the only problem is writing the macro.

8:37 tomoj: but at macro-time there's no way to know if a variable will be referenced :(

8:38 Chousuke: I mean, with-open or something is easy, but... if you like a challenge, try a (c++ "int main() { return 0; }") D:

8:39 tomoj: referenced?

8:40 all you need to do is generate the needed checks.

8:40 tomoj: referring to something fsm said above

8:40 Chousuke: I mean, it doesn't matter if the macro expands into a mess of nesting ifs

8:40 tomoj: something like (lazy-let [a (foo) b (bar)] (if true a b)) would never call bar

8:40 fsm: yes, my issue is more with my knowledge level than any issues with the language

8:41 macros are like having 26 letters of the alphabet, and deciding to write a book

8:41 Chousuke: heh.

8:41 tomoj: like I said I think you can get that by replacing a and b in the body with (force a) and (force b) and wrapping the foo/bars in delay, but that means every access to a is a function call

8:41 Chousuke: fundamentally, macros aren't so magical.

8:42 they're merely functions that transform a data structure to another. pretty common, right?

8:42 AWizzArd: Is there a way to declare the return values of functions?

8:42 fsm: alternatively, like sitting in front of google.com, you can search for anything you can imagine, you just have to have a good imagination

8:42 Chousuke: the magic comes from the fact that the output data structure happens to be code.

8:42 fsm: i am going to try that force/delay and i am going to look at how let is implemented

8:43 Chousuke: fsm: force and delay will only help with very expensive computations though.

8:43 cark: i'd go for macros

8:43 Chousuke: fsm: they have their own overhead.

8:43 cark: just make a macro that expand into your nested ifs

8:43 there will be no overhead, and you get readable code in the end

8:44 Chousuke: macros are useful if you can find a repeating pattern in your code

8:44 fsm: it is interesting to see what affects performance and what does not

8:44 Chousuke: if the ifs don't have a pattern, then it's a bit more difficult I suppose.

8:44 fsm: i am now at the point where about half my CPU time is in calculating dot products, and i think that is limited by the jvm

8:45 Chousuke: are you using clojure vectors or arrays or something java?

8:46 fsm: i am using double-arrays, once Rich & co put the pieces together for me about how to avoid boxing/unboxing

8:46 (actually just changed to floats, which was worth another 30% boost)

8:46 it is interesting that sometimes where you are tempted to use macros, the code runs slower

8:47 apparently the jvm hotspot stuff is clever, and/or it is more important to stay in cache

8:47 Chousuke: heh

8:47 too much inlining can harm performance because code doesn't fit in cache.

8:48 so it may actually be faster to do lots of function calls than to inline the function at the call sites.

8:49 tomoj: I am glad I don't need to understand that stuff :)

8:49 fsm: someone posted the link on hacker news the other day, and i got a couple thousand visits

8:49 there is quite some interest in clojure i guess

8:49 Chousuke: of course, hotspot is designed to let you stop worrying about such things.

8:50 ideally, you just write functions and use them normally and hotspot inlines them if needed

8:50 liwp: Chousuke: also, the JVM will only optimise code below a certain size, so if you function is too large HotSpot will ignore it.

8:50 But I have no idea how this applies to code generated by the Clojure compiler...

8:53 fsm: anyway, the main thing is I am confident that clojure is not causing any particular performance drop over java, having looked through the profiling results

8:53 Neronus: Well, as clojure functions are (I believe static) java functions, and at least my clojure functions are pretty short (especially to some java methods I've seen and written), my guess would be, that functions generated by clojure tend to be pretty short

8:55 Chouser: fsm: what was the popular link?

8:55 fsm: originally, it was http://tu.be/tracer but it is now hosted at cray.googlecode.com

8:56 liwp: Neronus: sounds reasonable. So is each clojure function compiled into a Java class with a static member function and that function implements the clojure function?

8:56 Chouser: ah, your ray tracer. very good.

8:56 fsm: I think someone was watching the clojurebot's del.icio.us feed

8:56 Chouser: a clojure function is compiled to a Java class with an instance function named 'invoke'

8:56 clojurebot: clojure is a language to use if you want to up your game

8:57 liwp: Chouser: and there is one class per clojure function?

8:57 Neronus: liwp: That's what I imagined, but I wouldn't bet my life on it. OTOH, clojure functions implement clojure.lang.IFn, so I guess they are instances of some kind :)

8:57 Chouser: each different-arity body in the fn becomes a matching-arity overload of the 'invoke' method

8:58 liwp: ok

8:58 Chouser: there is one class per fn, one instance of it per closure

8:58 the class ctor takes args for the values it closes over

8:59 tomoj: so an anonymous function in a loop means a fn class is instantiated each time through?

9:00 cark: just like in c# =)

9:00 tomoj: er, actually I guess there's only one closure there?

9:00 cark: ~function is also <Chouser> there is one class per fn, one instance of it per closure

9:00 clojurebot: Alles klar

9:00 tomoj: well... now I'm confused

9:00 AWizzArd: Chouser: do you know if it is possible to declare/type-hint the return value of a function?

9:01 Chousuke: I suppose in a loop you'd be generating multiple closures :/

9:01 Chouser: AWizzArd: (defn #^ReturnType foo [])

9:01 tomoj: but e.g. map with an anon function is just one closure

9:01 Chouser: ,(let [fns (for [i (range 3)] (fn [j] (+ i j)))] ((second fns) 3))

9:01 clojurebot: 4

9:02 AWizzArd: Chouser: good, thanks.

9:02 Chouser: there we have one class for (fn [j] ...), with three instances stored in the fns seq

9:03 the ctor to that class takes a single arg, the value of i for that instance.

9:03 here's an implementation detail I learned recently. I wouldn't bet on this working in future until you hear otherwise:

9:03 ,(let [fns (for [i (range 3)] (fn [j] (+ i j)))] (.i (second fns)))

9:03 clojurebot: 1

9:04 liwp: heh

9:04 Chouser: the closed-over value is currently stored in a public field with the same name as the local you closed over

9:05 liwp: sounds like something that will not work in the future with all likelyhood ;_)

9:15 fsm: ok, i changed from agents to pmap

9:16 now, the overhead of parralelizing my code is barely more than adding a setting for number of cores, and adding the letter p

9:19 and, any possible thread-unsafe code is confined to one line

9:22 there are obvious possibilities in increasing developer mean time to heart attack

9:24 AWizzArd: Can one make doseq or map work with a java.util.Enumeration?

9:24 Chouser: ,(doc enumeration-seq)

9:24 clojurebot: "([e]); Returns a seq on a java.util.Enumeration"

9:25 AWizzArd: thx

9:26 konr: what do you use as shortcuts to evaluate form, evaluate file, open repl, etc?

9:29 AWizzArd: in Emacs?

9:30 konr: or in any editor... I want to bind my keys in vi, but not sure what to

9:30 mikem: konr: for vim, you want to check out vimclojure

9:30 ~vimclojure

9:30 clojurebot: vimclojure is http://kotka.de/projects/clojure/vimclojure.html

9:31 konr: mikem: haha, I use it, but it doesn't set keybindings

9:31 mikem: konr: it does for me... have you looked in the docs?

9:32 konr: by default each command is preceded by <leader>, which in vim by default is \ (backslash). so to start the REPL, for instance, I type \sr

9:33 konr: mikem: hmm, it also does that for me, but isn't it a little inconvenient to type three keys [\ e t] to do that? I'm considering changing that to C-something

9:41 mikem: konr: there's a blurb in the doc file (~/.vim/doc/clojure.txt) about mapping commands to keys but first prepending them with <Plug>Clojure. have a look

10:14 konr: mikem: thanks, I'll take a look!

10:50 ankou: hi is Programming Clojure still a beta book or is it finally finished?

10:51 Chouser: ankou: you can buy it in book stores

10:52 ankou: I would prefer to have it as an ebook

10:53 Neronus: ankou: Chouser provided the answer: You can buy it in stores, ergo it is no beta book anymore

10:53 ankou: makes sense, thanks

11:04 krumholt__: ankou, you can buy it in pdf format

11:04 ankou: I just did it:)

11:04 weissj: anyone know if it's still being updated?

11:07 liwp: does anyone heard anything of this: Definitive Guide to Clojure (The Definitive Guide) by Luke VanderHart

11:07 I didn't know that there was another clojure book in the works...

11:10 Chouser: I seen the web page for that, plus heard about 1 or 2 more in the works besides.

11:10 I had seen

11:18 Licenser_: in what way is clojure bundled tightly with XML?

11:33 leafw: hi, any alive

11:34 I would like to understand the following destructuring: [k & ks :as keys] keys

11:34 this is a slot in a let declaration in the first part of Rick's talk on clojure for lispers

11:35 so what is ":as keys" doing?

11:35 Chouser: ,(let [[k & ks :as keys] (range 5)] {:k k :ks ks :keys keys})

11:35 clojurebot: {:k 0, :ks (1 2 3 4), :keys (0 1 2 3 4)}

11:35 leafw: aha

11:36 it preserves the whole, beyond the destructuring part.

11:36 thanks Chouser.

11:36 a pointer to the whole, rather.

11:36 Chouser: :as binds something to the whole original collection

11:36 right

11:36 ,(let [[k & ks :as keys] '[a b c d e]] {:k k :ks ks :keys keys})

11:36 clojurebot: {:k a, :ks (b c d e), :keys [a b c d e]}

11:37 Chouser: note it doesn't even call seq on the collection before it binds

11:37 leafw: aha, so its the exact thing.

11:37 Chouser: right

11:37 leafw: makes sense.

11:37 i.e. what I'd expect.

11:58 Licenser: Chouser: sorry I was ofline

12:03 Like the biggest part of the libraries on the clojure page is 'Category: xml'

12:05 and in a lot of places I found mentioned that Clojure is good for working together nicely with XML

12:05 Chousuke: that has little to do with Clojure itself. It just shows people need XML tools :)

12:06 rsynnott: lots of them, to try to make working with xml a little less hideous

12:06 Chousuke: I think Clojure is just pleasant for XML work because it's easy to build a DSL for representing XML as clojure data structures.

12:07 and because it's so easy, everyone has their own :P

12:07 Chouser: the jvm ships with an xml parser with a horrible api, so it's natural to provide a nice api wrapper around it

12:08 Chousuke: besides, XML is not that bad.

12:08 sure, it's overused and abused (ant...) but it's pretty good still.

12:09 Chouser: better than everyone rolling their own packed binary format

12:09 Chousuke: you have a way for describing your data in a way that lets you to stop worrying about writing a checker for well-formedness etc.

12:10 I don't know if there are any tools for writing schemas for json or validating against such, but I'm not aware of any :/

12:10 for XML, you have eleventy billion implementations.

12:15 * Chousuke glared at LispReader for using package-private methods in its implementation

12:16 Chousuke: Apparently I can't use them from my reader, even though it's clojure.lang.reader :/

12:19 I guess I could make a macro using reflection to get around pesky access restrictions.

12:20 Licenser: I find XML hugely overused

12:20 it is often used when other things are way simple

12:20 cark: hum by the way ... how do i do this : i have a with-something macro, and it's supporting with-something* function, the function is declared private. when i call the with-something macro from another namespace, i get an error

12:20 because the function is private

12:20 Licenser: like ant, or the java web application stuff, tomcat etc

12:21 cark: so the question is this : how would i go about calling this private function from my macro

12:22 OlafG26784859392: Hey people

12:22 rottcodd: cark: I think this works (#'ns/fn args)

12:23 cark: ah thanks i'll give it a try

12:23 OlafG: That's better

12:24 I need some help

12:25 rsynnott: Chousuke: none of which work properly ;)

12:25 (I'm thinking particularly of SOAP, here)

12:26 OlafG: I want to run a clojure script

12:26 but I'm not sure how to install it correctly on ubuntu server

12:46 Chouser: OlafG: fetch the clojure jar, then: java -cp clojure.jar clojure.main your-script.clj

12:47 OlafG: Yeah, I found a guide

12:47 and, you're the guy I'm looking for

12:47 hehe, I want to use your irssi to html script

12:47 weissj: in a related question, how to i run the repl and have it automatically load a file without havnig to first call (load-file) at the prompt

12:48 OlafG: Chouser: Can't seem to be able to download it from github though :/

12:48 cark: weissj : clojure automatically loads user.clj from the classpath

12:49 weissj: cark: so my file has to be named user.clj? or maybe i can just put the load-file call there?

12:49 cark: either way =)

12:49 weissj: cark: cool

12:51 Chousuke: hmm

12:51 Fossi: hi

12:51 * Chousuke forgot how to force paredit to delete a paren

12:52 Chousuke: I somehow managed to get them unbalanced.

12:52 Fossi: does somebody know a quick way of adding a java classpath to swank? i'm sick of having to put them in my .emacs

12:52 Chousuke: also, symbol resolution is insane business.

12:52 Fossi: Chousuke: C-SPC right C-X or such ;)

12:53 OlafG: argh

12:53 Fossi: at least with CUA you can force fix them

12:53 (and also break them quite easily)

12:53 Chousuke: hm

12:53 I force-inserted a rebalancing paren and deleted the extra sexp :P

12:54 Fossi: to the point that i think about mapping everything to sexp handling and get rid of backward-kill-word and left/right and so on

12:54 it's annoying

12:54 OlafG: wow, clojure sounds like complicated shit

12:54 krumholt__: is there a way that load-file will not load a file form by form? i want to write a function foo that uses a function bar. now i have to defn bar above foo or the file will not load. is there another way of loading the file?

12:54 Fossi: OlafG: it's the shit. might get compilicated if you want to ;)

12:55 OlafG: Hehe, firstly I just want to run a script, but not sure if I can mange even that:P

12:55 cark: krumholt__ : you can use declare

12:55 though that's not exactly what you asked

12:55 rhickey: Nice: https://jira.terracotta.org/jira/browse/CDV-1171

12:56 * Fossi hasn't followed terracotta in a long time

12:57 krumholt__: cark, then i would still have to declare every function. i want load-file to figure out the order of evaluation for me :)

12:57 Chouser: OlafG: you're having trouble downloading clojure.jar or the irssi stuff?

12:57 OlafG: irssi stuff

12:57 also, last time i tried I couldnt run it

12:57 Fossi: so i guess that's a no then for my emacs/swank question? :(

12:58 cark: krumholt__ : what if you have mutually recursive functions ?

12:58 Chouser: well, I put it up on github more for transparency and backup purposes than with the thought that anyone else would want to use it.

12:58 OlafG: oh, haha, was googling for a way to convert irssi logs to html

12:58 cark: krumholt__ : anyways i guess you could read form by form do your ordering then evaluate ...but it seems fragile

13:00 rhickey: :( https://jira.terracotta.org/jira/browse/CDV-1238

13:00 Chouser: OlafG: it may be useful to you as a starting point, but it's not packaged up or particularly pretty. You'll probably have to adjust the code at least a little.

13:00 OlafG: Oh

13:00 cark: krumholt__ : you would need a code walker, and macroexpansion ... which might not work if the macros are not defined yet

13:01 Chouser: rhickey: that should be too terrible for Clojure code, should it? who uses 'identical?' on strings?

13:01 krumholt__: cark, i guess my question just was. is there already a way to do it or do i have to do it myself

13:02 rhickey: Chouser: symbols and keywords do

13:02 OlafG: Chouser: Do you know another way to convert them to html and maybe split them? I really liked the splitting thing

13:02 cark: krumholt__: i think you'll have to do it yourself

13:03 rhickey: probably only an issue for the few symbols/keywords created in the Java code with string literals, relying on the interning

13:03 clojurebot: for is a loop...in Java

13:04 cemerick: rhickey: all strings going into Symbol are interned, so this shouldn't be an issue, should it?

13:05 rhickey: Symbol.create allows you to create a symbol from a known-interned string

13:05 cemerick: ah, I've never used create

13:06 I'd say, drop Symbol.create...two extra intern calls aren't going to hurt anything?

13:06 rhickey: 59 uses in Clojure impl

13:07 easy enough to make create call intern anyway

13:07 cemerick: even so -- I can imagine most people not knowing/caring what string interning is, and using Symbol.create.

13:08 liwp`: is there an (all?) predicate in core?

13:08 or contrib

13:09 cemerick: ,(doc every?)

13:09 clojurebot: "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

13:09 liwp`: thanks

13:10 Chousuke: ,(identical? `+ `+)

13:10 clojurebot: false

13:10 Chousuke: hmm, good. :P

13:11 though I'm still not sure if I'm creating symbols properly in my resolve-symbol function :/

13:11 rhickey: https://www.assembla.com/spaces/clojure/tickets/182

13:11 Chousuke: it feels very hacking to create symbols and then use str on those symbols when feeding them as parameters to (symbol ...)...

13:11 hackish

13:12 rhickey: ,(symbol 'foo)

13:12 clojurebot: foo

13:12 cemerick: rhickey: what sort of API compat are you assuming on the Java back-end? e.g. you might as well eliminate Symbol.intern AFAIC

13:13 Chousuke: rhickey: oh, it works on symbols too. duh. I wonder why I thought it would need strings :/

13:14 rhickey: cemerick: I don't want to eliminate anything at the moment

13:15 Chousuke: http://gist.github.com/174831 here's what I have right now. it seems to produce the correct results for most things.

13:15 * Chousuke probably shouldn't shadow so many names...

13:17 rhickey: Very pretty Tom - thanks! http://richhickey.github.com/clojure-contrib/

13:18 What do we need to do the same for Clojure core API docs?

13:20 weissj: has anyone had any experience trying to attach eclipse debugger to clojure's jvm?

13:21 * weissj just wonders if i should bother trying

13:23 rhickey: weissj: while it should 'just work', there can be issues in that these IDE debuggers presume the code will be Java - but give it a try, Clojure does support JSR-45, you might need to tell the debugger where the Clojure source is. JSwat works w/o any explicit Clojure support, and NB+enclojure, IntelliJ+LaClojure have explicit support

13:24 weissj: rhickey: ok, i'll give it a try and post the results here

13:24 i can't deal with netbeans, it runs too slow on this machine

13:28 replaca: rhickey: no problem!

13:29 rhickey: I need to think about the core stuff a little bit more. Mostly, I just need to parameterize a bunch of stuff, but there'll be some magic getting and running the right version

13:29 rhickey: I'll prototype on a fork, then we can discuss

13:37 weissj: hm, i am not able to set breakpoints in clojure files in eclipse ui. is there some other way to set them?

14:06 alrex021: I am trying to give clojure-maven-plugin 1.0 a spin but am struggling a bit to get it to work. (Example thats in git is our of date and doesn't run my end) Anyone using v1.0 of the plugin?

14:11 fdaoud: alrex021: I managed to get something to work

14:12 alrex021: fdaoud: I just changed the plugin info to point to new groupId etc... that seems to be going..

14:12 fdaoud: right

14:12 I don't think I needed to do anything else special

14:14 alrex021: I now get "2 required artifacts are missing. ... 1) com.theoryinpractise:clojure-maven-example:jar:1.0-SNAPSHOT 2) org.clojure:clojure-contrib:jar:1.0-SNAPSHOT"

14:15 no 1 seems to be referring to the example itself

14:18 fdaoud: alrex021: right, I changed that to something like hello/hello

14:21 LauJensen: Can new new be used to extend existing classes?

14:21 fdaoud: alrex021: I also think that the plugin is fussy about the namespace, the name of the source file, and the directory where the file is located

14:23 Chouser: LauJensen: that's all it can do

14:23 LauJensen: Chouser, extend something like JLabel by adding/overriding methods ?

14:24 Chouser: it can't add methods

14:25 oh... "you can add new (e.g. helper) methods not in any super, must have different name (can't add overloads to supers). No way to call those from outside the methods other than via reflection"

14:26 LauJensen: Ok, So no means yes :)

14:26 Chouser: but no way to supply args to the parent class' ctor

14:27 LauJensen: k - I dont recall ever having had that need

14:28 Chouser: I've used that feature of proxy several times, but there are often other ways to solve such problems.

14:29 LauJensen: Interop tends to get messy... when I do it

14:31 My return from using new new, would that then be this potentially anonymous class that I can interact with throughout my code?

14:35 Chouser: yes

14:35 alrex021: fdaoud: I got my own example to work now. Just need to add diff remote repo as maven default didn't seem to have org.clojure artifacts.

14:37 LauJensen: New new will really put me back in business with my JMonkeyWrappers. I choked on the interop

14:39 Chouser: LauJensen: nearly anything you will be able to do with newnew you can already do with proxy, except on the performance front.

14:39 fdaoud: alrex021: which repo did you use? i think i found it on tapestry

14:39 LauJensen: Chouser - I cant remember what exactly it was, but I got very far with proxy, and then this...

14:39 ~proxy

14:39 clojurebot: proxy is <Chouser> proxy teases with its ease of use, then suddenly betrays.

14:39 Chouser: yeah. I'm not sure how much newnew will help you there.

14:40 alrex021: fdaoud: http://tapestry.formos.com/maven-snapshot-repository/

14:40 LauJensen: If I can both add and override methods, It'll get me where I need to go

14:40 Chouser: in fact, it may be worse. newnew is primarily about creating new clojure stuff that runs very fast. proxy is primarily about java interop.

14:41 I think it's more likely that proxy will gain more interop features than that newnew will.

14:43 LauJensen: Hmm.. The main archetecture of JMonkey, is that you get a few basic classes that you extend into objects that govern every part of the game, ie weatherobject, physicsobjects, vehicleobject and so on. Proxy couldnt do it and I didnt have the patience for gen-class.

14:46 Chouser: I think it would be possible for proxy to provide a thread-safe way to call superclass methods, like gen-class :exposes

14:47 well, both :exposes and :exposes-methods

14:48 that would reduce proxy's tendency toward betrayal a bit

14:48 proxy's pattern for doing init and post-init is already better than gen-class'

14:52 LauJensen: ok... I really wouldnt know :)

15:16 Fossi: "This kind of lexical intercourse" <3 graham

15:27 hiredman: holy dependency downloads batman

15:28 running ant in a checkout of clojureql's repo downloads ivy, then uses ivy to download clojure, clojure-contrib, apache derby, etc

15:30 java.lang.Exception: Unable to resolve symbol: lazy-cons in this context (backend.clj:81)

15:30 :(

15:31 ah, old clojureql jar hanging around

15:37 Fossi: recently i had a case where i had a pattern for map entries: key and some rather largish codeblock that only differed in a few spaces

15:38 is there a way to capture that into a macro without wrapping the whole or leaving the key part out?

15:38 i can't return 2 distinct values from macros or is there a way?

15:40 tomoj: Fossi: huh? what do you want to do

15:40 Chouser: I don't understand what you're trying to do. You're right that a macro can only return a single form, but often you can use (do first-thing second-thing)

15:40 Fossi: let me try to scetch that up

15:40 lisppaste8: url

15:40 lisppaste8: To use the lisppaste bot, visit http://paste.lisp.org/new/clojure and enter your paste.

15:44 Fossi pasted "untitled" at http://paste.lisp.org/display/86027

15:44 Fossi: it was a little more bloated on the right, but something along those lines

15:44 and i have a whole bunch more of those handlers

15:46 and i wanted to keep the "token" along with the handler in the definition although it wouldn't really be needed in any of the cases (yet)

15:47 Chouser: handle-stuff is a fn -- you want to call the same one for each value, just with different args?

15:50 Fossi: actually, the handle-stuff isn't even in there

15:51 Chouser: ok. well, anyway, I doubt you need a macro

15:52 how about (-> (add-handler "token1" render-func1 :option1 true) (add-handler ...))

15:52 er

15:52 Fossi: well, ok, might work with a function as well

15:52 Chouser: (-> {} (add-handler "token1" render-func1 :option1 true) (add-handler ...))

15:52 there

15:52 Fossi: yeah, that's what i meant with "wrapping the whole"

15:53 it changed the structure of the code

15:53 i didn't want to do that

15:53 *changes

15:53 Chouser: then (defn add-handler [the-map token-key render & options] (assoc the-map token-key {:render-func render-func ...})

15:54 oh, you want to keep { ... } around the whole thing?

15:54 Fossi: that's why i suspected a macro might help. to generate something in that place without changing the map structure

15:55 well, it's pretty much random, so i might actually, practically change it later, but i wanted to know whether it's possible somehow

15:56 but if i can only return a list from a macro or function i don't see how

15:56 *single

15:56 i guess i could wrap the whole into another macro

15:57 Chouser: it's an interesting thought. one could almost wish for a defsplicemacro that always returns a seq of things to be spliced in.

15:58 Fossi: i think the wrapping macro idea would work without changing the structure too much

15:58 Chouser: well, you wouldn't need your own wrapping macro. -> already exists and would suffice in this case I believe.

15:59 Fossi: ie, just having a macro around that changes {(macrocall) (macrocall)} into {(first (macrocall)) (rest (macrocall))...

15:59 * Fossi didn't quite get the feel of -> yet :)

16:00 Chousuke: too bad you can't just do `{~(generate-code) ~(generate-code)} :/

16:00 Fossi: ah. well -> wouldn't let me keep the 'mappiness'

16:00 i guess

16:01 i now realize this would be a really stupid place to do this anyway ;D

16:01 Chousuke: ,`{1 ~@(list 1 2 3)}

16:01 clojurebot: {1 1, 2 3}

16:01 Chousuke: ,`{~@(list 1 2 3 4)}

16:01 clojurebot: 1

16:01 Chousuke: reader problem :/

16:02 Fossi: hmmm. interesting idea though

16:02 Chousuke: ,{1}

16:02 clojurebot: java.lang.ArrayIndexOutOfBoundsException: 1

16:02 Chousuke: hmm

16:02 Fossi: gotta love those error messages

16:03 Chousuke: :)

16:03 Fossi: at first you go "wtf"

16:03 then it's "WTF?!!!"

16:03 Chousuke: the implementation just shines through a bit :P

16:03 Fossi: and after a while it's just "oh, i forgot a value in some map. ah, there it is"

16:04 "a bit" ;D

16:07 Chousuke: so, why exactly doesn't that work?

16:10 Chousuke: Fossi: I'm not sure.

16:10 Fossi: it almost seems to do what i want

16:11 Chousuke: Fossi: probably because in {~@(whatever)} the map only has one element so it can't be read in the first place, but in {1 ~@(whatever)} there are two elements so the map can be read before the splicing happens.

16:11 Chouser: well, you're still wrapping the whole thing, if only in a `

16:12 Fossi: agreed, but it seems there is no way without wrapping the whole

16:15 hiredman: do clojureql calls need to be wrapped with something besides with-connection?

16:15 I run my insert-into statement, get {:table jobs, :columns (:name), :env ("Rascals")} back, but the table appears to be empty

16:19 Fossi: n8

16:40 wavister: does memoize use soft references?

16:41 hiredman: ~def memoize

16:41 cark: ~def memoize

16:41 !

16:41 hiredman: ugh

16:41 chrome does not like github

16:41 cark: works for me

16:41 hiredman: looks like it uses a normal persistaent map

16:43 alrex021: in clojure is there a way to get the name of function that we are currently in? (Something like in java ..this.getClass().getName())?

16:43 wavister: yup... ok. but that's cool. i could re implement that with a weak map or something

16:47 Chouser: alrex021: for logging or something?

16:47 alrex021: yes, exactly, very simple logging using println to be exact

16:48 I'm in -main, so want to print .... (println fn-name " .... ")

16:48 or any other func for that matter

16:49 Chouser: I can't think of any way to get that currently

16:51 alrex021: No worries, I take its something you wouldn't want to perhaps do often in fp. I'm curious to know though how does logging framework, if currently any, handle this?

16:51 Chouser: not all code has a top-level fn name that would mean anything

16:52 you can get the current file name

16:52 ,*file*

16:52 clojurebot: "NO_SOURCE_PATH"

16:53 Chouser: ,(.getLineNumber (first (.getStackTrace (Exception.))))

16:53 clojurebot: 0

16:54 Chouser: that could get you a line number at runtime.

16:54 I suppose between the two, you might be able to find the .clj source and construct an appropriate name

16:55 alrex021: Chouser: thanks

17:42 krumholt__: there is no difference between a struct and a map or is there? a struct is just a nice way if you have to create a similar map over and over again?

17:43 citizen428: i'm trying to download a file via http from within my clojure program... i was thinking duck-streams, but i can't seem to figure it out. any pointers?

17:46 replaca: citizen428: there's a nice example on the doc for http-agent for doing an http download with duck streams

17:47 http://richhickey.github.com/clojure-contrib/http.agent-api.html

17:47 citizen428: replaca: really? i have looked for something like that half the day... :( thanks a lot!

17:48 Chouser: krumholt__: a struct is a kind of map. other kinds of maps include hash-maps and sorted-maps.

17:48 replaca: citizen428: np

17:49 Chouser: I do wish for better string and char literals. Perhaps I should give some thought to what they would be...

17:53 krumholt__: Chouser, so they are all maps with different implementations? but they do the same thing. should this bother me in any way?

17:54 Chouser: krumholt__: they each have their own benefits and drawbacks, but all provide a common interface and make a common set of promises. This should make you joyful. :-)

17:55 for example, you can use assoc to insert a key/value into any of them, they will all do this persistently -- a common interface with a common promise

17:55 krumholt__: Chouser, so in the end i coult just change (def foo (hashmap ...)) to (def foo (sorted-map ..)) and everything still works. ok then i will worry about what the benefits of each map type are later

17:55 Chouser: that's right.

17:56 krumholt__: thanks

17:57 Chouser: well, everything that's promised will work. From the docs, "Hash maps require keys that correctly support hashCode and equals. Sorted maps require keys that implement Comparable, or an instance of Comparator."

17:57 lots of objects provide both and so can be keys of either.

17:57 krumholt__: i use keywords as keys

17:58 Chouser: those will work great in hash maps, sorted maps, struct maps, and array maps. :-)

17:59 krumholt__: ok thanks :)

18:24 mudphone: hey folks, anyone know what the type hint is for a String array?

18:24 or better yet, where I can find a comprehensive list of type hints?

18:28 krumholt__: i would guess you can type hint every java class?

18:29 mudphone: well, my questions is... for example, for an array of bytes, the type hint is #^bytes

18:29 I want to know what the type hint syntax is for a String[]

18:29 hiredman: ,(class (into-array ["foo" "bar"]))

18:29 clojurebot: [Ljava.lang.String;

18:29 mudphone: #^Strings

18:29 hiredman: mudphone: why are you type hinting an array of strings?

18:30 no

18:30 #^bytes and such are special cases hardwired into the compiler

18:31 mudphone: we're calling a Java library

18:31 hiredman: thanks, but why do you ask? Is it a bad idea?

18:32 the library takes a String[] as one of its arguments

18:32 we're wrapping it

18:32 hiredman: mudphone: just pass it a String[]

18:32 no need for type hinting

18:33 mudphone: Won't it use reflection to make the Java call then?

18:33 hiredman: mudphone: I am pretty sure it won't

18:33 mudphone: we profiled our process and saw a lot of time in reflection (in general)

18:33 hiredman: you can set *warn-on-reflection* and see

18:34 the reflection stuff happens because the type signauter for clojure Fn's is all based on Object

18:34 but jave methods have specific type signatures so reflection should not be needed

18:34 mudphone: fot the *warn-on-reflection* setting, where do we set that? and trigger it?

18:35 hiredman: hmm

18:35 hiredman: (set! *warn-on-reflection* true)

18:35 ,(doc *warn-on-reflection*)

18:35 clojurebot: "; When set to true, the compiler will emit warnings when reflection is needed to resolve Java method calls or field accesses. Defaults to false."

18:35 mudphone: do we have to compile to see that? or just run as normal?

18:35 (ie ahead of time)

18:36 hiredman: no, you don't need to do aot compiling

18:36 just keep in the mind warning happens at compile time (when code is loaded) as opposed to when it is running

18:36 mudphone: so you just see standard output then?

18:37 ah

18:37 hiredman: p=> (defn f [x] (.toString x))

18:37 Reflection warning, NO_SOURCE_PATH:234 - reference to field toString can't be resolved.

18:37 mudphone: so, for example, eval-ing the buffer in emacs will give you your warning?

18:37 hiredman: dunno, don't use emacs

18:37 mudphone: what editor do you use?

18:37 hiredman: vim

18:38 mudphone: ah

18:42 hiredman: ~performance

18:42 clojurebot: Titim gan éirí ort.

18:42 hiredman: bah

18:43 ~performance is <reply>http://clojure.org/java_interop#toc46

18:43 clojurebot: Ok.

18:43 mudphone: hiredman: thanks, it gives the warning in via the slime repl (in emacs), in case you ever come to the dark side

18:45 jfields: what would I used in clojure to create a single result from a seq. I'm looking for something similar to Ruby's inject.

18:46 mudphone: reduce?

18:46 ,(doc reduce)

18:46 clojurebot: "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val is supplied, returns the r

18:46 jfields: cool. thanks.

18:47 hiredman: inject is such a weird name for that

18:47 clojurebot: for is not a loop

18:48 hiredman: clojurebot: shut it

18:48 clojurebot: Titim gan éirí ort.

19:03 bitbckt: hiredman: That's why it's aliased as #reduce in Ruby 1.9... thankfully.

19:03 (and finally)

19:37 lowlycoder: is there a good example of a clojure server serving clojure repls over tcpip anywhere?

19:51 tomoj: lowlycoder: well have you seen http://richhickey.github.com/clojure-contrib/server-socket-api.html ?

19:51 not an example,but..

19:51 cark: doesn't swank just do that ?

19:52 tomoj: if you run your code inside emacs, I guess?

19:52 cark: you can use swank without emacs

19:53 tomoj: I'd love to see an example of that too, then :)

19:55 mikem: there's also the nailgun server that comes with vimclojure

19:55 bryteise: http://blog.asymmetrical-view.com/2009/08/20/emacs-slime-remote-repl.html

19:55 lowlycoder: tomoj: nice; thanks

19:55 i find nailgun/vimclojure to be unstable

19:56 the code is so short and elegant, there must be a catch

19:56 tomoj: bryteise: awesome, thanks

20:24 cark: did compojure's redef eventually make it to contrib ?

20:42 Chouser: should clojure finger-trees be designed with an eye toward IEditableCollection?

20:42 clojurebot: clojure is like life: you make trade-offs

20:42 Chouser: should they produce seqs with chunks of 2 to 4, or just non-chunked seqs?

22:11 hiredman: ~ping

22:11 clojurebot: PONG!

22:19 hiredman: clojurebot works on a newer fnparse, if anyone cares

22:19 dmix: I can't get slime to work with swank for some reason, when I hit M-x slime I get this error (in aquamacs): http://gist.github.com/175252 this is my .emacs http://gist.github.com/175255

22:21 hiredman: looks like swank is not on your classpath

22:21 JAS415: yep

22:21 dmix: how do I add it to my classpath?

22:21 hiredman: ~classpath

22:21 clojurebot: classpath is (System/getProperty "java.class.path")

22:22 dmix: "/Users/dmix/src/swank-clojure:/Users/dmix/Library/Clojure/lib/clojure.jar:/Users/dmix/Library/Clojure/lib/jline.jar:/Users/dmix/Library/Clojure/lib/clojure-contrib.jar"

22:22 er

22:22 so it is in the classpath

22:22 swank-clojure

22:23 JAS415: so you can add it to the .clj or i think there is an emacsen way to do it

22:23 hiredman: uh

22:23 what is in /Users/dmix/src/swank-clojure?

22:23 dmix: hiredman: swank-clojure.el swank/ etc

22:24 hiredman: just because you have some directory that has "swank" in it's name on your classpath it does not mean swank is on you classpath

22:24 what is in swank/

22:24 dmix: a bunch of clj's

22:25 ie swank.clj

22:25 hiredman: that sounds good

22:26 maybe add a "/" after swank-clojure

22:26 JAS415: can't you do wildcards

22:27 hiredman: JAS415: if he has JDK1.6 he can

22:27 JAS415: I have one that is '~/hacking/clj/current-work/*:'

22:27 it loads all of my 'current work'

22:27 although right now that's a mash of things

22:28 so could do same with swank folder

22:28 needs the : after the * though, for some reason..

22:32 dmix: alright, got it working, I cloned the latest git swank-clojure and put it in a new folder, then added it to the class path

22:32 thanks btw

23:27 djkthx: is there a short-hand for defining a case-insensitive regex using the # reader macro?

23:35 hiredman: ,(re-find #"(?i)foo" "FOO")

23:35 clojurebot: "FOO"

23:35 hiredman: (?i) means case insensative in java regexs

23:36 djkthx: ah, interesting

23:36 i was always used to seeing it like /asdf/i

23:36 thanks!

23:49 mebaran151: I can't seem to get the new enclojure plugin to work: it can't find clojure contrib pretty print even thought clojure contrib is in my classpath

23:49 anybody have any tips?

23:51 hiredman: did you compile clojure contrib properly?

23:58 mikem: hiredman: do you mean compiling it like so: ant -Dclojure.jar=../clojure/clojure.jar

23:59 hiredman: yes

Logging service provided by n01se.net