#clojure log - Apr 08 2009

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

0:03 hiredman: http://googleappengine.blogspot.com/2009/04/seriously-this-time-new-language-on-app.html <-- java on app engine

0:05 cmvkk: aw, Groovy, Scala and JRuby get a mention but not Clojure. is this still a second-class JVM language?

0:08 danlarkin: hey now

0:08 that's a neat thing

0:09 durka42: maybe it will get mentioned when we implement it :)

0:10 * hiredman waits for an email to tell him more

0:11 durka42: great minds think alike

0:11 * danlarkin too

0:11 hiredman: did someone just grab the clojure1 app identifier?

0:11 durka42: clojurebot: great minds think alike is <reply>and fools rarely differ

0:11 clojurebot: In Ordnung

0:11 durka42: ~great minds think alike

0:11 clojurebot: and fools rarely differ

0:12 hiredman: cause I tried to get clojure1, the check availability button said it was availble, then when I clicked "next" it said it was in use

0:15 Drakeson: is there something similar to map that applies the function f first to the whole coll, then to (rest coll), then to (rest (rest coll)), etc. (as opposed to applying f to (first coll), then (second coll), etc. ?

0:16 cmvkk: not built in, to my knowledge

0:16 Chouser: (map foo (take-while identity (iterate next coll)))

0:17 Drakeson: wow, (iterate next coll) is a nice idiom. thanks

0:19 cmvkk: iterate-while might be a worthwhile function to have

0:19 Chouser: "For instance, an app cannot spawn threads" ...google app engine

0:19 cmvkk: it's come up

0:19 cmvkk: hmm

0:19 Chouser: oh

0:19 take-while identity has come up, I think

0:20 durka42: hmm, no threads could be an issue

0:20 cmvkk: does clojure implicitly use threads or something?

0:21 i don't mean with agents, of course

0:21 Chouser: http://groups.google.com/group/clojure/msg/f88b1675635837a2 -- iterate-while

0:22 hiredman: No, an App Engine app may not spawn new threads

0:22 oh

0:23 cmvkk: so, when you send to an agent, are you spawning a thread?

0:23 if not, when do the threads in a thread pool get spawned?

0:23 or is it more subtle than all that.

0:27 hiredman: cmvkk: when you send-off, the executor must be creating a thread

0:27 cmvkk: yes. but with send, maybe it's not as clear

0:28 how often are agents used in web application code anyway?

0:28 hiredman: with send the threadpool creates the threads when it is created

0:29 cmvkk: right, and when is the threadpool created?

0:29 hiredman: how does that matter?

0:29 cmvkk: if it's created the first time you use send, then you can use any clojure code as long as you don't use agents.

0:30 if it's created no matter what, or something, then won't it be a problem for any clojure code?

0:31 durka42: i suppose it would depend on how silently google makes spawning threads fail

0:32 i don't know the answer to your question

0:32 cmvkk: right. if google kills the process if it tries to spawn a thread, it might be a problem.

0:33 durka42: ,(.getPoolSize clojure.lang.Agent/pooledExecutor)

0:33 clojurebot: 1

0:33 durka42: in my repl (having not used any agents yet) that returns zero

0:34 ~javadoc clojure.lang.Agent

0:34 hiredman: uh

0:34 durka42: er

0:34 i don't expect that to work

0:34 hiredman: ~def c.l.Agent

0:34 durka42: ~javadoc java.util.concurrent.ThreadPoolExecutor

0:35 cmvkk: based on that test, it seems like there's not really a problem, though.

0:35 durka42: ,(.getCorePoolSize clojure.lang.Agent/pooledExecutor)

0:35 clojurebot: 3

0:36 durka42: setCorePoolSize Sets the core number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle. If larger, new threads will, if needed, be started to execute any queued tasks.

0:36 that sounds like they still aren't created unless there are tasks on the queue

0:39 slashus2: The thread pool is created when the agent is created.

0:40 ?

0:43 durka42: no, it is a static member

0:43 ,(.pooledExecutor (agent nil))

0:43 clojurebot: java.lang.IllegalArgumentException: No matching field found: pooledExecutor for class clojure.lang.Agent

0:43 slashus2: okay

0:43 durka42: ^- wat

0:49 slashus2: So all send-off's use the same thread pool?

0:49 * slashus2 implementation details are interesting.

0:49 durka42: i think the pooledExecutor is for send

0:49 send-off's are handled by the soloExecutor

0:49 i think

0:50 slashus2: ,(.pooledExecutor clojure.lang.Agent)

0:50 clojurebot: java.lang.IllegalArgumentException: No matching field found: pooledExecutor for class java.lang.Class

0:50 durka42: ,(.getPoolSize clojure.lang.Agent/soloExecutor)

0:50 clojurebot: 1

0:50 dnolen: first public GAE app?

0:50 http://guestbook-clj.appspot.com/

0:50 slashus2: ,clojure.lang.Agent/pooledExecutor

0:50 clojurebot: #<ThreadPoolExecutor java.util.concurrent.ThreadPoolExecutor@197f158>

0:50 slashus2: ,(clojure.lang.Agent/pooledExecutor)

0:50 clojurebot: #<ThreadPoolExecutor java.util.concurrent.ThreadPoolExecutor@197f158>

0:50 dnolen: nice write up here

0:50 http://elhumidor.blogspot.com/2009/04/clojure-on-google-appengine.html

0:51 durka42: cool!

0:52 this demands playing with this weekend

0:53 cmvkk: that was fast

0:53 cp2: oh nice

0:54 slashus2: http://guestbook-clj.appspot.com/exercise What do you make of this?

0:54 * durka42 notices that the atom value there jumped after everyone in this channel clicked on it

0:55 cp2: heh

0:55 haha

0:55 anon anon anon...

0:55 kinda like debian random generator

0:55 9 9 9 9 9 ..

0:56 slashus2: Why exactly is the atom value jumping around?

0:56 dnolen: yeah AppEngine is distributed across JVMs so you really can't really on refs/atoms

0:56 slashus2: ooh

0:57 That is the number of visitors.

0:57 * durka42 is still waiting for an email...

0:59 hiredman: me too

1:00 dnolen: that doesn't make sense to me

1:00 well

1:00 hmmm

1:01 dnolen: hiredman: could be wrong, but I think what happens is the first request is handled by one jvm

1:01 the next request might not be.

1:01 slashus2: google broke it :-(

1:01 durka42: so if you don't write something out to disk it's not guaranteed to persist across requests?

1:02 hiredman: no write to disk

1:03 dnolen: well not to disk, but to whatever store google provides.

1:03 durka42: well database or whatever

1:11 hiredman: http://fragmental.tw/2009/04/08/clojure-on-google-app-engine/

1:30 durka42: hey, it's an email

1:30 hiredman: !

1:31 me too

1:31 durka42: however, bedtime

1:31 * durka42 .finalize()

2:17 kadaver: ok guys time to launch compojure apps on appengine!

2:18 hiredman: it's been done, at least twice already

2:22 slashus2: Does Common Lisp have multi-methods comparable to clojure's?

2:23 cmvkk: it has the object system

2:23 which allows you to define methods

2:23 but it isn't like clojure

2:24 slashus2: CL's methods can dispatch on value?

2:25 cmvkk: no, they dispatch on class type.

2:25 that's why it isn't like clojure.

2:25 slashus2: Hmm, I am getting some mixed information.

2:25 cmvkk: well, don't take my word for it...

2:25 if someone is telling you otherwise, they're probably right.

2:26 slashus2: I don't know about that.

2:26 cmvkk: my understanding is that CLOS is just a regular object system. you define classes, then you define methods which dispatch on the class of each argument.

2:28 blbrown: is everyone on the appengine train

2:29 hiredman: yes

2:34 lisppaste8: jauk pasted "Problem with lazy parsing of xml" at http://paste.lisp.org/display/78235

2:34 jauk: I can't get the lazy parsing of xml working correctly

2:35 If anyone has time to look at the code above, I would appreciate it

2:35 i'm still a newbie with lisp (java background)

2:36 hiredman: no exceptions?

2:37 I am unfamiliar with that lib, but the call to first, then the call to zip/node is very odd

2:38 jauk: well, with the default ram it gives finally outofmemoryexception

2:38 but with xMx=1000m xMs=1000m it just freezes

2:39 hiredman: you are sure it is not doing any work?

2:39 how large is finland.osm?

2:39 jauk: well, it is doing work. but the idea would be that because of lazy parsing it shouldn't need to do much any work.

2:40 hiredman: that is a naive idea

2:40 jauk: finland.osm is quite large, 513 megs in total

2:40 hiredman: hmm

2:40 jauk: is it?

2:41 hiredman: ~lazy

2:41 clojurebot: lazy is hard

2:41 jauk: in the comments of the lazy-xml lib (http://github.com/dysinger/clojure-contrib/blob/36d13c6d40750b80b612921d5b3499d3a6c2fdb5/src/clojure/contrib/lazy_xml.clj):

2:41 ; When used with zip and zip-filter, you can get do queries like this

2:41 ; without parsing more than the first few tags:

2:41 ; (zip/node (first (xml-> (zip/xml-zip tree) :id)))

2:41 this is why i thought it should work

2:43 hiredman: maybe it should

2:52 lisppaste8: jauk annotated #78235 "Further details" at http://paste.lisp.org/display/78235#1

2:59 jauk: hiredman: thanks for your input! i guess i'll have to ask the question again later if someone else would have had experience with the lazy-xml library...

3:00 hiredman: Chouser is the xml filter guy, he is on central time (US) I believe

3:00 there is also always the google group

3:02 jauk: ok, i'll have to ask him then, thanks! i didn't want to start by spamming the google-group with a newbie question :) (maybe there should be separately a stupid questions -group?)

3:48 dysinger: GAE yayz

5:36 leafw: any help with vimclojure

5:37 I forgot how to view the help page ...

5:37 kotarak is not here, *sigh*

5:38 Neronus: leafw: maybe :help vimclojure

5:38 leafw: Or the doc directory whereever you installed the package

5:53 leafw: Neronus: :help vimclojure I tried, and variations, but didn't wokr

5:53 yeah the help is in a file; was just wondering how to access it from within vim

6:17 AWizzArd: ~ seen rhickey

6:17 clojurebot: no, I have not seen rhickey

6:17 AWizzArd: ~ max people

6:17 clojurebot: max people is 164

7:43 cemerick: is there some usage for condp floating around somewhere? I don't quote grok it.

7:50 AWizzArd: ,(doc condp)

7:50 clojurebot: "([pred expr & clauses]); Takes a binary predicate, an expression, and a set of clauses. Each clause can take the form of either: test-expr result-expr test-expr :>> result-fn Note :>> is an ordinary keyword. For each clause, (pred test-expr expr) is evaluated. If it returns logical true, the clause is a match. If a binary clause matches, the result-expr is returned, if a ternary clause matches, its result-fn, which must be a unary function, is called

7:51 AWizzArd: ,(condp = (+ 5 4) 10 'it-is-10 9 'no-it-is-9)

7:51 clojurebot: no-it-is-9

7:51 AWizzArd: ,(condp #(+ 1 %) (+ 5 4) 10 'it-is-10 9 'no-it-is-9)

7:51 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: sandbox$eval--1583$pred--1585

7:52 AWizzArd: yeah, nonsense

7:52 Well, it takes the expression and does (pred exp clause), until there is a match

7:53 cemerick: yeah. I guess I just don't have a use-case for it.

7:54 AWizzArd: It is just less repetetive than

7:54 ,(cond (= 10 (+ 5 4)) 'it-is-10 (= 9 (+ 5 4)) 'no-it-is-9)

7:54 clojurebot: no-it-is-9

7:54 AWizzArd: where I need to repeat = and (+ 5 4) over and over again

7:55 cemerick: yeah, I got that. I just thought that there might have been more to it.

9:17 Lau_of_DK: Hey guys

12:20 danlarkin: quietest I've ever seen this channel!

12:20 pjstadig: shhh

12:20 clojurbot: whose job is it to keep danlarkin quiet?

12:20 clojurbot: who's job is it to keep danlarkin quiet?

12:21 danlarkin: you're spelling his name wrong

12:21 pjstadig: clojurebot: who's job is it to keep danlarkin quiet?

12:21 clojurebot: Titim gan �ir� ort.

12:21 pjstadig: clojurebot: whose job is it to keep danlarkin quiet?

12:21 clojurebot: that is alek_b's job

12:21 danlarkin: whose is correct, not who's

12:21 pjstadig: fourth time is the charm

12:21 danlarkin: sweet

12:21 rsynnott: why does that thing speak Irish?

12:26 pjstadig: so

12:26 one of the major issues left with Clojure + TC is the fact that you cannot assign a non-portable value as the root binding of a var

12:27 the most glaring example is *in*, *out*, and *err*

12:27 what we need is a way to specify specific values to share, and specific values to exclude

12:28 AWizzArd and I have been talking about it and I think he has some good ideas

12:28 we could add metadata values to specific vars that we would want to share

12:28 instead of automatically sharing everything

12:30 then the trick would be to fracture the namespace map so that when a var is resolved it is either fetched from a shared or a non shared mapping

12:30 is there a better way to do it?

12:32 anyone? anyone? bueller?

12:32 AWizzArd: rhickey maybe has an idea? :)

12:33 pjstadig: ~def clojure.lang.Namespace

12:34 * Neronus loves his emacs. There's always something new to learn, or if everything has been learnt, invent

12:40 pjstadig: the only problem i foresee is classes

12:40 if you add a var to the TC graph whose value is a compiled function

12:41 for that function to be used in another VM its class would have to get added to the graph

12:41 which could be done

12:41 but if that function depends on other functions those classes would have to be added as well

12:42 the only way around it might be to just add all of the classes into the TC graph

13:13 rhickey: pjstadig: It's too complex to explain here, but I am keeping in mind these TC issues in my work now on namespace modularity

13:14 Cark: hum i've fallen behind on the mailing list, did you talk about these changes there yet rhickey ?

13:14 kotarak: hmm... couldn't with-ns go to ns-utils instead of having a dedicated namespace?

13:17 rhickey: Cark: no changes yet to discuss

13:18 Cark: ok thanks ! i'm only slightly shaking at the thought of breaking changes

13:18 rhickey: Cark: This is for down-the-line post 1.0

13:18 clojurebot: for is not a loop

13:18 Cark: ah nice =)

13:18 ~chouser?

13:18 clojurebot: chouser is ruthless about breaking other people's code

13:19 * rhickey is enjoying the relative peace post 20090320 release

13:20 Neronus: is variable lookup in clojure performant, or is it always a good idea to avoid using vars?

13:20 rhickey: Any plans when 1.0 will be released? And is there a roadmap available, or is it all in your head?

13:21 Chouse1: rhickey: there's some pre-lazier verbage on clojure.org yet. I deleted a couple lines from "sequences", but there's still stuff in "lisps"

13:21 Cark: neronus : might be usefull to enclose a tight loop with a (let [myvar *myvar*]

13:24 AWizzArd: ,((fn [& args] (map class args)) 1 2 3)

13:24 clojurebot: (java.lang.Integer java.lang.Integer java.lang.Integer)

13:24 AWizzArd: ,(defmulti foo (fn [& args] (map class args)))

13:24 clojurebot: DENIED

13:24 AWizzArd: okay, if I do this defmulti, and then (defmethod foo '(Integer Integer Integer) [i] (print "Integers: " i))

13:25 (foo 1 2 3) ==> IllegalArgumentException: Wrong number of args passed to: user$fn

13:25 kotarak: AWizzArd: (defmethod .... [i] <- *m��p*

13:26 AWizzArd: Ah I see, it m��ps at that point.

13:26 Neronus: hehe.. moeep

13:27 AWizzArd: if I replace the [i] with [& i] now it funnily says: IllegalArgumentException: No method for dispatch value: clojure.lang.LazySeq@4319aced

13:28 kotarak: Try using vectors for the dispatch value.

13:32 rhickey: Chouser_: ok, thanks, welcome back!

13:33 Neronus: 20090320 is feeling like a 1.0 release candidate to me, we (the community) have to have a discussion about what 1.0 means, esp. re: patching etc

13:35 Neronus: the roadmap is in my head and somewhat in issues, and as always driven by what is happening, where people's (including my own) interests lie etc

13:37 cemerick: are there any expectations around patching at all? Very large frameworks might backport patches, but that's not at all a typical expectation in most environments (short of security-related stuff, if any).

13:42 jauk: Chouser_: i'm trying to do lazy xml parsing but with a huge xml file (500 megs) the application would seem to consume huge amounts of memory. do you have any tips? some code is here: http://paste.lisp.org/display/78235

13:43 rhickey: cemerick: I imagine 1.0 is all about patching - being able to get fixes without new enhancements or breaking changes

13:44 eevar_: rhickey: http://clojure.org/lisps -- the paragraph on sequences looks dated

13:44 rhickey: eevar_: yes, some of the site needs touchups to correspond to last release

13:47 Cark: jauk : i don't know the xml stuff, but it seems to me that a zip will retain all of the data, as it's supposed to be able to reconstruct the full thing

13:47 cemerick: rhickey: breaking changes, no, but without new enhancements? That's an unnecessary burden, I think (again, outside of security fixes).

13:49 jauk: Cark: ok, it could be that it just doesn't make sense to load a 500M xml. I was just hoping that with lazy evaluation it would just under the hood fetch only those items that are needed for computing the expected result (in the case of the example, the first matching node)

13:50 rhickey: cemerick: well, that's a topic for discussion - many people want 1.0 so they don't have to contend with 'changes' generically, rarely distinguishing breaking from non. Any core name introduction is potentially (trivially) 'breaking' code that used that name for something else

13:50 Cark: jauk : try doing your processing without the ziper

13:52 stuhood: rhickey: another way to distinguish breaking from non-breaking changes is to use major/point releases

13:52 jauk: Cark: hmm, i could try that

13:52 stuhood: rhickey: going straight to 1.0 instead of 0.9.* may be rushing things

13:53 cemerick: rhickey: eh, that's what :except is for in ns.

13:53 I know that if we backported all fixes to each major release of our product, we'd go absolutely batshit insane.

13:54 rhickey: cemerick: I'm not arguing for or against, as I personally don't need 1.0. Those that do need to articulate what it means to them, and we need to see consensus

13:54 cemerick: rhickey: yeah, I know I'm arguing with the wind here :-)

13:55 rhickey: AFAIC, those that want fixes in the releases branch can backport them

13:55 cemerick: more important than what it means is who's going to do that maintenance?

13:55 rhickey: cemerick: precisely

13:55 jauk: Cark: it was just that the comments in lazy_xml seem to suggest that xml-zip can be used in a lazy fashion: http://paste.lisp.org/display/78235#1

13:55 rhickey: who other than me

13:56 cemerick: right. And if you're not going to do it (thank goodness!), then what's the real point behind a v1.0 release w.r.t. patches (it certainly has good PR benefits).

13:56 * cemerick can argue with the wind *all day* :-)

13:56 Cark: jauk : right, but what if you access something toward the end ? the zipper will keep it all in order to be able to reconstruct the full xml

13:57 rhickey: cemerick: there will be a release branch, a policy for patches (fixes only), a version labeling system 1.0.1 etc

13:57 jauk: Cark: true. in the example code, i'm trying to access the first sub-node in the xml file, so - in theory - that should work ok?

13:58 rhickey: Other than the PR side, my impression is that people want 1.0 for stability, but wouldn't consider that they are getting that if there were no fixes other than those on trunk

13:58 they can fix on a release or an SVN version right now

14:00 but aren't satisfied with that

14:00 jauk: Cark: thanks for your input! it might be that the approach of using xml-zip with a huge xml file is flawed. this whole lazy evaluation is quite difficult for a java coder to handle :)

14:00 rhickey: bbl

14:00 Cark: jauk : don't take my word for it

14:00 cemerick: obviously, it's very hard for me to see the argument

14:20 clojurenoob: Probably a stupid Q (I'm not too familiar with Java/JVM): are Clojure-compiled programs particularly amenable to decompilation compared to regular Java code?

14:23 AWizzArd: clojurenoob: yes, in some sense. I tried it, and while JAP can decompile, it produces programs that can't be compiled with javac again

14:23 The code itself is not really human readable

14:24 clojurenoob: AWizzArd: are the names of functions mostly preserved?

14:24 AWizzArd: They still exist.

14:24 So people could read your function names in clear text.

14:24 We have two solutions for that

14:24 One is: use a java obfuscator

14:25 jauk: i guess one could make a java bytecode -> clojure decompiler

14:25 AWizzArd: jauk: yes

14:25 Chousuke: You'd think the dynamicism makes decompilation less likely to produce anything understandable.

14:25 AWizzArd: right

14:26 clojurenoob: while a obfuscator would be a good solution, you can also use a second method, a simple macro trick

14:26 You write a macro which replaces defn

14:26 This macro creates another defmacro

14:26 It adds your function to a global vector

14:27 Your macro manages all magic to find the right function out of your vector

14:27 So, (defsecret foo [x] (+ x 20)) allows you to still say (foo 100) ==> 120

14:27 clojurenoob: That's all very informative. Thanks!

14:27 AWizzArd: but (foo 100) will be ra macro

14:27 duncanm: can i put metadata in non-Clojure objects?

14:28 AWizzArd: and it will produce something like: ((get secret-functions 14) 120)

14:28 clojurenoob: then no function name will be readable in clear text

14:28 instead people could only see how you fetch functions out of this vector

14:28 duncanm: oh

14:28 clojurenoob: AWizzArd: wouldn't you need some kind of code walker to look for all function applications? (non-trivial presumably)

14:29 duncanm: symbols and collections

14:29 sigh

14:29 AWizzArd: clojurenoob: no, you would use the defsecret macro only for functions that you write yourself.

14:29 clojurenoob: OK

14:29 AWizzArd: If you use existing clojure libs then their function names would stay readable.

14:30 kotarak: duncanm: you can implement clojure.lang.IMeta/clojure.lang.IObj with your object. Then they support meta/with-meta.

14:31 AWizzArd: ~ seen AWizzArd

14:31 clojurebot: AWizzArd was last seen in #clojure, 0 minutes ago saying: ~ seen AWizzArd

14:32 pjstadig: clojurebot: ~seen clojurebot

14:32 clojurebot: no, I have not seen ~seen clojurebot

14:32 hiredman: clojurebot: seen clojurebot?

14:32 clojurebot: Of course I have seen myself.

14:32 pjstadig: ah

14:33 duncanm: so the COND in Clojure is not like COND in Scheme in that it has an implicit BEGIN, is that right?

14:33 AWizzArd: pjstadig: the ~ is instead of "clojurebot:"

14:33 pjstadig: yeah i know

14:33 i realized afterward

14:33 kotarak: duncanm: no. It has no implicit do.

14:33 hiredman: "the definition of a lagacy application is one that works"

14:34 clojurenoob: I'm curious, Clojure seems like one of the most popular functional languages these days. How come it's still not in the ShootOut? (GHC, OCaml, SBCL and some virtual unknowns are)

14:34 duncanm: in Scheme (if test (begin (a) (b)) (begin (c) (d))) can be written (cond ((test (a) (b)) (else (c) (d))))

14:34 kotarak: ah

14:34 kotarak: duncanm: (cond test (do (a) (b)) :else (do (c) (d)))

14:35 duncanm: right

14:35 in that case, it's not that much shorter than using IF

14:35 AWizzArd: clojurenoob: it is too new

14:35 Clojure started to take off after Summer 2008

14:35 kotarak: duncanm: it is for more than one test

14:36 hiredman: and the shootout is generaly not well enough thought of for anyone to bother with it

14:36 AWizzArd: clojurenoob: I think sooner or even sooner Clojure code will appear for the shootout. Maybe you will be the first to submit an entry ;)

14:38 cconstantine_: I have the shootout on my computer, and I plan on doing some of the tasks for clojure (once i know clojure better and can really represent it)

14:38 I expect clojure to get performance very simlar to Java 6 Server

14:39 AWizzArd: I think this is not possible yet for these micro benchmarks.

14:39 hiredman: cconstantine_: generally the tasks in the shootout aren't long runner tasks

14:40 clojurenoob: Most shootout submissions start as lame entries by a noob. Then some angry expert rewrites them.

14:40 AWizzArd: Yes

14:40 cconstantine_: yeah, I understand. If the solution involves compiling the .clj and running the resulting .class it should be near-identical to native java

14:40 pjstadig: maybe instead we could just make Chouser angry

14:40 and he'll write it to start with

14:40 cconstantine_: hehe

14:41 * cconstantine_ writes a "bogo" solution to every shootout problem.

14:41 hiredman: I don't think anything jvm based is really going to shine in short run tasks

14:41 cconstantine_: some of them aren't all that short-running

14:41 AWizzArd: Although Java does pretty well in the shootout.

14:42 cconstantine_: java does very respectably.

14:43 hiredman: I found ibm devzone article that said java object allocations take about 10 machine code instructions, while C++ takes around 100

14:43 cconstantine_: it does better than my spelling at the very least

14:43 clojurenoob: I'm also curious to see what a high-performance Clojure code would look like. Haskell code in the shootout is ugly, for example. (knucleotides, spectral norm, n-bodies). Clojure is "pure functional". How would you be mutating arrays (in n-bodies and others)?

14:43 hiredman: clojure is not "pure functional"

14:44 Chousuke: clojure is not purely fun... damn you

14:44 clojurebot: clojure is like life: you make trade-offs

14:44 hiredman: clojurebot: botsnack

14:44 clojurebot: thanks; that was delicious. (nom nom nom)

14:44 Chousuke: clojure is perfectly capable of working with mutable java arrays :)

14:44 Cark: use java arrays !

14:44 cconstantine_: You don't mutate arrays in clojure. Every "modification" returns a new array with the modification in place. There are some very fancy things going on behind the scenes for that to be very fast

14:44 hiredman: cconstantine_: a vector is not an array

14:45 cconstantine_: ok, array-like thinger

14:45 hiredman: "Clojure is an effort in pragmatic dynamic language design"

14:45 Chousuke: cconstantine_: Those are vectors. you can mutate Java arrays.

14:45 clojurenoob: Chousuke: I understand that, but doesn't mixing in mutation dangerous if you also want multithreading, etc?

14:45 hiredman: cconstantine_: you can make a normal java array

14:45 Chousuke: clojurenoob: sure.

14:45 cconstantine_: using a normal java array isn't very clojure-ish

14:45 hiredman: java arrays are very mutable

14:45 Chousuke: clojurenoob: that's why normal clojure code doesn't use java arrays very often :)

14:45 the immutable data structures are nicer.

14:45 AWizzArd: Someone in here posted a link to this video: http://www.infoq.com/presentations/click-fast-bytecodes-funny-languages

14:45 hiredman: the keyword in that quote from http://clojure.org/rationale is pragmatic

14:46 AWizzArd: There a byte code expert explained that he found several things that Clojure could improve to run faster

14:47 hiredman: AWizzArd: I only heard two things

14:47 tagged numbers and clojure does a lot of ephemeral object creation

14:47 which isn't reall much of a slow down when you have a good gc and fast object allocation

14:48 cconstantine_: would there be any benefit to having objects with the same value cached, so the next creation of a value-equal object would just return the already allocated object?

14:48 AWizzArd: ,(time (dotimes [i 1000000] (inc i)))

14:48 clojurebot: "Elapsed time: 54.802 msecs"

14:49 hiredman: cconstantine_: I doubt it

14:49 AWizzArd: try this loop in pure Java

14:49 hiredman: object allocation on the jvm is very cheap

14:49 cconstantine_: hiredman: I can see (very easily) how the caching mechanism would be more costly than the allocation/gc

14:49 clojurenoob: Chousuke: when you do use mutable Java arrays (for performance) in the context of a bigger application in Clojure (possibly multithreaded), how do you mentally prove that using those mutable Java arrays is safe?

14:49 clojurebot: for is not used often enough.

14:49 Chousuke: clojurenoob: you're just careful

14:50 clojurenoob: or you copy them every time they exit your function

14:50 cconstantine_: clojurebot: the reason to use the immutable types is that it saves you from all that stuff; if you don't use them you don't get the benefit.

14:50 clojurebot: Ok.

14:50 Chousuke: mutable arrays are meant to be used "locally" in clojure

14:50 hiredman: http://www.ibm.com/developerworks/java/library/j-jtp01274.html

14:51 Chousuke: ie. you shouldn't store data that is passed around a lot in java arrays

14:51 hiredman: "The JIT compiler can perform additional optimizations that can reduce the cost of object allocation to zero."

14:52 Chousuke: ,(time (dotimes [i 1000000] (let [i (int i)] (inc i))))

14:52 clojurebot: "Elapsed time: 59.995 msecs"

14:52 Chousuke: hmm

14:52 actually

14:52 ,(time (dotimes [i 1000000] (unchecked-inc i)))

14:52 clojurebot: "Elapsed time: 55.9 msecs"

14:53 AWizzArd: Try this in pure Java:

14:53 ,(time (let [x (make-array Integer/TYPE 1000000)] (dotimes [i (count x)] (aset-int x i i)) x))

14:53 clojurebot: #<int[] [I@6258e1>

14:53 "Elapsed time: 653.335 msecs"

14:54 Chousuke: not too bad :/

14:54 AWizzArd: it is not bad

14:54 hiredman: ,(time (amap unchecked-inc (.toArray (range 1000000))))

14:54 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$amap

14:55 AWizzArd: It just is for some reason (which I don't know) just dramatically much slower than Java.

14:55 hiredman: ,(time (amap unchecked-inc (make-array Integer/TYPE 1000000) (.toArray (range 1000000))))

14:55 clojurebot: java.lang.IllegalArgumentException: Wrong number of args passed to: core$amap

14:55 AWizzArd: no, not dramatically, but it *is* slower

14:55 hiredman: ,(doc amap)

14:55 clojurebot: "([a idx ret expr]); Maps an expression across an array a, using an index named idx, and return value named ret, initialized to a clone of a, then setting each element of ret to the evaluation of expr, returning the new array ret."

14:57 hiredman: ,(amap (.toArray (range 1000000)) 0 (make-array Integer/TYPE 1000000) inc)

14:57 clojurebot: java.lang.Exception: Unsupported binding form: (make-array Integer/TYPE 1000000)

14:57 hiredman: ok

14:57 how the hell does amap work?

14:58 ,(amap (.toArray (range 1000000)) 0 a inc)

14:58 clojurebot: java.lang.RuntimeException: java.lang.RuntimeException: java.lang.Exception: Unsupported binding form: 0

14:58 AWizzArd: hiredman: http://groups.google.de/group/comp.lang.lisp/browse_frm/thread/b24b85f18fee26d7/64a1f1e5ec115ac7?tvc=1#doc_20e2e2efb795f3cf

14:59 hiredman: AWizzArd: what is this?

14:59 AWizzArd: There is an example program in Clojure.

15:00 In that thread I optimized it a bit, so it runs much faster than the initial version.

15:00 But there is still something in which could be faster.

15:00 hiredman: does it show me how to use amap?

15:01 AWizzArd: no ;)

15:01 I didn't try that

15:01 hiredman: ,(.toArray (range 1000000))

15:01 clojurebot: #<Object[] [Ljava.lang.Object;@1984161>

15:01 hiredman: ,(into-array Integer/TYPE (range 1000000))

15:02 clojurebot: #<int[] [I@1cc946b>

15:02 AWizzArd: I used (int-array ..)

15:02 ,(doc int-array)

15:02 clojurebot: "([size-or-seq] [size init-val-or-seq]); Creates an array of ints"

15:02 hiredman: ,(int-array (range 1000000))

15:02 clojurebot: #<int[] [I@a8cd58>

15:02 hiredman: ,(amap (int-array (range 1000000)) idx ret inc)

15:02 clojurebot: java.lang.IllegalArgumentException: argument type mismatch

15:03 AWizzArd: ~def amap

15:04 pjstadig: ,(amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget-int r x))))))

15:04 clojurebot: java.lang.Exception: Unable to resolve symbol: aget-int in this context

15:04 pjstadig: ,(amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x))))))

15:04 clojurebot: #<int[] [I@bde56d>

15:04 hiredman: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x)))))))

15:04 clojurebot: #<int[] [I@607135>

15:05 "Elapsed time: 179.273 msecs"

15:05 hiredman: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x)))))))

15:05 clojurebot: #<int[] [I@1e0312b>

15:05 "Elapsed time: 9607.864 msecs"

15:05 pjstadig: ,(print (seq (amap (into-array Integer/TYPE (range 10)) x r (do (aset-int r x (+ 1 (aget-int r x))))))))

15:05 clojurebot: java.lang.Exception: Unable to resolve symbol: aget-int in this context

15:05 hiredman: woa

15:05 pjstadig: ,(print (seq (amap (into-array Integer/TYPE (range 10)) x r (do (aset-int r x (+ 1 (aget r x))))))))

15:05 clojurebot: (1 2 3 4 5 6 7 8 9 10)

15:05 pjstadig: just checking if it's doing what I think it's doing

15:06 clojurenoob: ,(range 10)

15:06 clojurebot: (0 1 2 3 4 5 6 7 8 9)

15:07 pjstadig: why is unchecked-add so much slower?

15:09 ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x))))))))

15:09 clojurebot: #<int[] [I@14cbf3f>

15:09 "Elapsed time: 168.047 msecs"

15:09 gnuvince: I'd like to know too; every single time I've tried an unchecked-* operation, it turned out a *lot* slower than the regular operator.

15:09 AWizzArd: pjstadig: try that now in TC :)

15:10 pjstadig: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x))))))))

15:10 clojurebot: #<int[] [I@16e1dd8>

15:10 "Elapsed time: 160.954 msecs"

15:10 pjstadig: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (int (aget r x))))))))

15:10 clojurebot: #<int[] [I@4b1bcd>

15:10 "Elapsed time: 171.053 msecs"

15:11 pjstadig: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x)))))))

15:11 clojurebot: #<int[] [I@1aea0c1>

15:11 "Elapsed time: 8850.087 msecs"

15:11 pjstadig: holy crap

15:11 ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (unchecked-add 1 (aget r x)))))))

15:11 clojurebot: #<int[] [I@1e84244>

15:11 "Elapsed time: 8873.324 msecs"

15:11 pjstadig: must be the int cast?

15:12 gnuvince: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r x (+ 1 (aget r x))))))

15:12 clojurebot: #<int[] [I@15a5aff>

15:12 "Elapsed time: 171.652 msecs"

15:12 gnuvince: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset r x (+ 1 (aget r x))))))

15:12 clojurebot: #<int[] [I@987e1e>

15:12 "Elapsed time: 149.145 msecs"

15:13 pjstadig: it looks like + is doing just about as well as unchecked-add

15:14 gnuvince: aset and + seem to be a tad faster than aset-int, unchecked-add and int

15:14 clojurenoob: addition probably isn't the bottleneck there. array read / write is more likely to be one. no?

15:15 Chousuke: (time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add 1 (int (aget r (int x)))))))))

15:15 oops

15:15 ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add 1 (int (aget r (int x)))))))))

15:15 clojurebot: #<int[] [I@10f7ec9>

15:15 "Elapsed time: 189.218 msecs"

15:15 Chouser_: literal ints are boxed

15:15 Chousuke: ,(time (amap (into-array Integer/TYPE (range 100000)) x r (do (aset-int r (int x) (unchecked-add (int 1) (int (aget r (int x)))))))))

15:15 clojurebot: #<int[] [I@798797>

15:15 "Elapsed time: 149.075 msecs"

15:16 hiredman: ,(time (.toArray (map inc (range 100000))))

15:16 clojurebot: #<Object[] [Ljava.lang.Object;@19cfefb>

15:16 "Elapsed time: 138.24 msecs"

15:16 Chousuke: I wish I knew how to write a compiler that could optimise that :(

15:16 hiredman: Chouser seems to have started on a self hosted compiler

15:17 AWizzArd: Maybe when Clojure is rewritten completly in Clojure then Rich will add gradual typing to it.

15:17 In that case Clojure could be in nearly each situation as fast as pure Java itself.

15:17 Chousuke: something simple like assuming that if one parameter is unboxed, then others are unboxed too

15:17 since mixing unboxed and boxed numbers is impossible anyway

15:18 hmm...

15:19 Yeah, I'm hoping that after the compiler is rewritten in clojure it'll get more attention :P

15:20 clojurenoob: GHC is written in Haskell, but real applications are lacking (despite the language being probably 20 years old)

15:21 * Chousuke is trying to get his easter pudding to be less frozen

15:22 Chousuke: easter pudding is funky stuff. looks like shit but tastes good.

15:22 both impressions are amplified with the addition of some cream

15:24 SethTisue: does anyone know what made Rich decide to rewrite Clojure in Clojure?

15:24 I asked him about this at Boston Lisp Meeting and he seemed kind of dismissive about it, like it wouldn't be worth the effort

15:24 wondering why he seems to have changed his mind.

15:24 pjstadig: Chouser is the one writing the Clojure compiler in Clojure

15:25 but Rich is generally supporting, i think

15:25 SethTisue: ohh, interesting.

15:25 ok, supportive if someone else does it :-)

15:25 AWizzArd: SethTisue: he explained it some days ago.

15:25 kotarak: SethTisue: He said something about it being easier to port to different platforms like .NET and such.

15:25 AWizzArd: gnuvince asked him 2 days ago or so

15:25 gnuvince: Saturday around noon iirc

15:25 AWizzArd: Also Clojure in Clojure would open the door for a static type system.

15:25 pjstadig: http://github.com/Chouser/clojure-compiler/tree/master

15:26 ~logs?

15:26 clojurebot: logs is http://clojure-log.n01se.net/

15:26 gnuvince: Basically he talked about: improved performance, doing things that cannot be done at the moment (accepting/returning primitive types), tool support, easier to port to other backends, etc.

15:27 SethTisue: hmm, that log site stops at Sunday

15:27 pjstadig: that brings up an interesting point though

15:27 SethTisue: making it more portable certainly makes a lot of sense

15:27 hiredman: SethTisue: rich has mentioned self-hosting has a post 1.0 priority

15:27 pjstadig: there seems to be some backlash in here about writing clojure libraries instead of using a Java lib

15:27 SethTisue: the other issues, I can imagine.

15:27 * Chousuke +1's Chouser for using :no-dot as an argument for munge instead of "true"

15:28 SethTisue: improved performane, though? really?

15:28 pjstadig: but if Clojure is hosted on .NET as well, then a pure clojure lib would be more portable

15:29 gnuvince: 11:17 < rhickey> gnuvince_: improved efficiency removes need to drop to Java - a new implements construct replaces proxy with code as fast as implement-the-interface-in-java

15:29 < rhickey> removal of any impediments keeping you from defining things like the data structures in Clojure itself

15:29 < rhickey> better modularity, see above

15:29 < rhickey> much easier porting to other hosts - JS, CLR, AS3, ObjC? etc

15:29 < rhickey> possible support for primitive args/returns

15:29 < rhickey> an accessible AST for tools, type systems etc

15:30 That's pretty much what he said.

15:30 Chousuke: pjstadig: I think if more clojure implementations start popping up then yeah, we'll need some kind of a portability library

15:30 but what to call it!

15:31 clojure.portability sounds weird :(

15:31 SethTisue: gnuvince: thx

15:32 Chouser_: I think there are a set of features that don't seem to hard in theory to add to the Clojure compiler, but when you look at the current Java implementation those additions suddenly look much harder

15:32 not to mention less fun, as they would require writing Java code.

15:33 So between that and ideas that Rich has had relatively recently about what features would be required to get clojure collections written in clojure to perform sufficiently, he may have changed his mind.

15:33 gnuvince: A large benefit of switching to Clojure-in-Clojure: one less thing Slava can use to criticize Clojure on proggit ;)

15:33 SethTisue: when I asked the q originally, fun was definitely one of the issues I had in mind. fun for other people contributing, too

15:34 eevar_: losing out on the whole java ecosystem sounds like a loss imo

15:34 gnuvince: SethTisue: that should be a large reason in favor of such a decision; if you can't attract people to hack with you, that's bad for the project.

15:34 SethTisue: eevar_: in what sense?

15:34 Chouser_: oh, we're not talking about replacing the JVM

15:35 eyeris: When I run this code, "new.xls" is still 0 bytes and java.exe never closes the file. Am I missing some Clojure detail (something about laziness, perhaps) or is this a problem with the library?

15:35 http://pastebin.ca/1386362

15:35 Chouser_: just replacing (most of) the .java code used currently to implement Clojure.

15:35 eevar_: okies, that makes more sense

15:35 gnuvince: The JVM is the whole point (I think) why Clojure took off so spectacularly

15:35 A nice clean Lisp with the largest library of any Lisp

15:36 eyeris: gnuvince: I think it is the vector syntax, etc. There have been Scheme implementations with decent java interop for a while, hasn't there?

15:37 Perhaps that's what you mean by "clean" :)

15:37 Chousuke: scheme doesn't have as nice a macro system though.

15:37 SethTisue: or the emphasis on immutability and concurrency

15:37 or the lack of historical baggage

15:38 Chousuke: (the problem with scheme's macro system is that I can't understand it. Clojure's is much simpler. :P)

15:38 SethTisue: :-)

15:38 hiredman: eyeris: without looking, it sounds like you need to .close the file

15:38 Chouser_: jauk: it seems to me that your lazyxml example ought to work -- it should parse all of the first <bound>...</bound> element, and not much more than that before returning

15:39 but I haven't tested the laziness of lazyxml or zipfilter since the lazier changes to clojure ... perhaps something broke.

15:39 eyeris: Oh man, now I feel silly. Thanks hiredman!

15:40 hiredman: :P

15:50 pjstadig: Chouser_: oh, we're not talking about replacing the JVM

15:50 gnuvince: < rhickey> much easier porting to other hosts - JS, CLR, AS3, ObjC? etc

15:50 what does it mean to port to other hosts?

15:50 clojurenoob: I'm very much a noob, but some aspects of Clojure seem clunky: strange OO (do people use it), appending to sequences creates different ordering of elements depending on type, True/T/False/Nil/'()/0/null is confusing (I prefer Haskell's approach there)

15:51 pjstadig: if you're depending on a java lib and clojure has been ported to CLR, then your program won't run on CLR

15:51 Chouser_: pjstadig: hm, good point. But the JVM would still be the "primary" host, especially where it's available.

15:51 pjstadig: yeah which mean's it's not necessarily insane to think about writing a pure clojure lib for processing CSV

15:51 Chouser_: pjstadig: right, most apps would not be written for "cross-virtual-platform" support

15:51 pjstadig: or making HTTP requests

15:52 i'm not saying it's the most sane thing to do either (it depends on the situation)

15:53 hiredman: clojurenoob: what OO?

15:53 AWizzArd: clojurenoob: Clojure generally wants to motivate you to *not* do OO

15:53 hiredman: data structures have different characteristics

15:54 Chouser_: OO is a pretty vague term

15:54 hiredman: vectors can grow at the end O(1), lists grow at the front O(1)

15:54 SethTisue: clojurenoob: I assume by strange OO you mean using maps for the purposes you'd use structs or classes in other languages?

15:54 hiredman: conj is just aware of this, and does the right thing for each

15:56 AWizzArd: And hashmaps can grow "anywhere" in near constant time

15:56 Chouser_: does it seem odd that sortedMap.insert(k, v) might do something different from hashMap.insert(k, v)?

15:56 AWizzArd: ,(conj {:a 10, :b 20} {:c 30})

15:56 clojurebot: {:c 30, :a 10, :b 20}

15:56 clojurenoob: I meant generic methods (or whatever they are called. it's been a while since I've watched the tutorials on bliptv)

15:56 Chouser_: multimethods

15:56 AWizzArd: What is about them?

15:58 Cark: if you don't like multimethods, don't use these

15:59 Chouser_: Here is some rationale about why clojure does multimethods and hierarchies the way it does, and what is desired for the future: http://groups.google.com/group/clojure/msg/0b500f0eba88eda1

16:01 Cark: the one time i thought i would use multimethods, i found that i was trying to do OO

16:01 so i reconsidered and went for standard high order functions

16:01 in the end, this code is now easier to read

16:03 hiredman: clojurebot: the world <reply>what the world needs is more higher order functions

16:03 clojurebot: In Ordnung

16:03 hiredman: clojurebot: what does the world need now?

16:03 clojurebot: Huh?

16:03 clojurenoob: AWizzArd: I can't answer in detail, because it's been a while since I've seen the tutorials. But when I saw them, I got the distinct feeling that there was something tasteless about multimethods. That's all I can recall. I was wondering if this feeling was shared by others.

16:04 hiredman: clojurebot: tell me what the world needs

16:04 clojurebot: Pardon?

16:04 hiredman: oh

16:04 pjstadig: for got 'is'

16:04 hiredman: clojurebot: the world is <reply>what the world needs is more higher order functions

16:04 clojurebot: You don't have to tell me twice.

16:04 hiredman: clojurebot: what does the world need now?

16:04 clojurebot: what the world needs is more higher order functions

16:05 pjstadig: clojurebot: what is our mascot?

16:05 clojurebot: the official mascot of clojure is a futuristic ninja robot

16:05 Chouser_: multimethods are used much less often in clojure than methods are in many languages (such as Java, python, ruby, etc.)

16:06 when you need a multimethod in clojure, they often fit quite nicely. Sometimes they solve a problem that would require extreme contortions in "standard" OO systems.

16:07 marklar: Chouser_: What does GF stand for in that post?

16:07 SethTisue: Gang of Four?

16:08 pjstadig: that would be GoF

16:08 GF = generic function

16:08 SethTisue: ok maybe not :-)

16:08 marklar: pjstadig: ah thanks

16:09 djpowell: Is http://code.google.com/p/clojure/downloads/list working?

16:10 pjstadig: maybe code.google.com is being DDoS'ed because of all the people trying to get information about GAE/Java

16:11 cconstantine_: Has anyone gotten into the Java AppEngine trial?

16:11 pjstadig: i think i did

16:11 cconstantine_: I have, and wonder if anyone has played around with clojure in it

16:11 pjstadig: i haven't tried to play with it yet

16:11 hiredman: http://www.thelastcitadel.com/_media/clojure.png

16:11 cconstantine_: same here

16:11 pjstadig: there are some blogs about using clojure on GAE

16:12 hiredman: clojurebot: delicious

16:12 clojurebot: delicious is http://delicious.com/clojurebot

16:12 pjstadig: sweet!

16:12 futuristic ninja robots!

16:15 yeah i can't pull up the clojure google code page

16:15 hiredman: I am in the java appengine trial

16:16 but, uh, I just did it without remembering I hate webapps

16:16 pjstadig: hehe

16:16 hiredman: so now I don't know what to do

16:16 djpowell: I just got into the trial too

16:17 kotarak: Does someone want to play as guinea pig *coughcough* beta tester with an Ivy patch to contrib?

16:21 djpowell: Eclipse with clojure-dev and google's clojure plugin is probably pretty cool

16:26 Chouser_: google has a clojure plugin?

16:28 dysinger: you meant google gae plugin probably djpowell

16:29 pjstadig: http://code.google.com/eclipse/

16:35 hiredman: http://jonasboner.com/talks/state_youre_doing_it_wrong/html/all.html (from reddit) mentions clojure and rhickey

16:35 djpowell: oh, er, yeah - I mean't google's eclipse plugin

16:54 eyeris: Does anyone here know the predicate form to use for "not equal to" in clojureql?

16:54 (not (= x y )) ;fail

16:55 (not= x y) ;fail

16:55 (<> x y) ;success?

16:56 cmvkk: not= isn't right?

16:56 pjstadig: ,(= 1 2)

16:56 clojurebot: false

16:56 cmvkk: ,(not= 1 2)

16:56 clojurebot: true

16:56 kotarak: eyeris: doesn't <> not work?

16:56 pjstadig: ,(not= 1 2)

16:56 clojurebot: true

16:56 kotarak: eyeris: should translate to SQL <>

16:56 eyeris: kotarak I think <> works, but I get a null pointer exception. I'm still tracking own if that is in my code or cql

16:57 s/own/down

16:57 kotarak: do you have an example?

16:57 eyeris: Not a simple one :) brb

17:07 djpowell: anybody tried the google stuff? i was trying it without compojure. i got a classloader error - maybe I should set *use-context-classloader* ?

17:09 eyeris: Is there a shortcut in VimClojure/Gorilla that will evaluate the outer-most s-exp of the block the cursor is in?

17:10 kotarak: eyeris: \et

17:10 EvaluateToplevel

17:11 eyeris: Thanks. I don't know how I misinterpreted the documentation to think "top-level" meant the buffer

17:11 kotarak: eyeris: the whole buffer is \ef (EvaluateFile)

17:13 eyeris: Why, when I place the cursor inside a defn and press \et, it returns nul instead of the new symbol?

17:14 kotarak: Is the cursor in the opening/closing paren?

17:14 I meant on the paren.

17:14 eyeris: No.

17:14 kotarak: Hmm... Which version are you using?

17:14 eyeris: Though I get the same behaviour if it is.

17:15 Where is the version number? I don't see it in clojure.vim

17:16 kotarak: eyeris: there probably is none. Did you download it or use the hg repo?

17:16 eyeris: It's definitely not 2.0. I didn't realize that was released.

17:16 I will upgrade to 2.0

17:16 kotarak: Uh. Pre 2.0? Still the Ruby version?

17:17 Please upgrade! Much better. I plan to release a new update around easter.

17:17 eyeris: Where do I put ng.exe?

17:17 kotarak: somewhere in your path.

17:17 Or set the vimclojure#NailgunClient variable to the place where you put it.

17:18 eyeris: What about ngserver?

17:18 kotarak: Somewhere in your PATH.

17:18 eyeris: Ok

17:19 You should really make it more difficult, so I don't look like such a dope asking :)

17:19 kotarak: hehe. There is a screencast on http://kotka.blip.tv showing the main points.

17:20 Uh.

17:20 The cast refers to the next release. Sorry for the confusion.

17:21 eyeris: Should I still be using Gorilla?

17:22 kotarak: No.

17:22 It is merged into VimClojure

17:22 You should remove the old gorilla files from your .vim directory

17:22 dakrone_hb: I have "(ns app.hello (:gen-class))" and " (defn -main [& args] (println "application works"))" in a clj file and I'm still getting "java.lang.RuntimeException: java.lang.ClassNotFoundException: app.hello$_main__10 (NO_SOURCE_FILE:0)" when I do a (compile 'app.hello), am I doing something wrong?

17:23 kotarak: dakrone_hb: is the src and the classes directory in the Classpath?

17:25 dakrone_hb: yea, the source in in "app/hello.clj" and my classpath has "." in it

17:25 kotarak: dakrone_hb: and the classes directory?

17:26 dakrone_hb: kotarak, it's not, the classes directory needs to be in the classpath also?

17:26 eyeris: Hrm. I removed Gorilla and now \ef just beeps

17:27 dakrone_hb: kotarak, that fixed it, thanks!

17:27 kotarak: dakrone_hb: yes, and it must exist.

17:27 dakrone_hb: yep, it works now

17:28 kotarak: eyeris: you have to put "let clj_want_gorilla = 1" into your .vimrc. And don't forget to start the ng-server before opening a clojure file.

17:31 eyeris: I have to compile NG myself?

17:32 That's annoying. I have no Java development tools (like Ant) installed on my Windows machine.

17:32 kotarak: put the line "nailgun-client=ng" into your local.properties. Then it should be automatically compiled. On Windows just use the ng.exe delivered with the distribution.

17:33 eyeris: ng.exe is the client and the server?

17:33 kotarak: It's the client.

17:33 The server must be started manually on Windows. (Some .bat guru around?)

17:33 java -cp <your-class-path> com.martiansoftware.nailgun.NGServer

17:34 eyeris: I can use the shell script provided via cygwin.

17:34 kotarak: java -cp <your-class-path> com.martiansoftware.nailgun.NGServer is actually better

17:34 eyeris: the script blows up on cygwin.

17:34 At least I had problems.

17:34 eyeris: I can write my own bat file then.

17:34 I just don't have Ant, so I can't compile the ngserver class files.

17:34 Without a tedious manual compile

17:35 kotarak: Pfew. Ant would help... You can look into the build.xml on how to compile the server files.

17:36 AWizzArd: kotarak: maybe you can include a shell script which will call a little clojure program which does the compile stuff and which builds a j

17:36 +ar

17:36 Then no dependencies are needed, such as ant, maven or even ivy

17:38 kotarak: AWizzArd: Wait a second for my post on the google group. Then you can test yourself.

17:44 dmiles_afk: is there a good reason to use ClojureCLR over Clojure on IKVM?

17:46 well i havent trie dlately on IKVM .. but it seems like it might work

17:47 eyeris: Does nil? match Java Nulls?

17:47 djpowell: yeah - nil is java null

17:48 duncanm: can I do internal DEFINEs in Clojure like I can Scheme?

17:48 hiredman: use let

17:53 duncanm: anyone using SLIME with Clojure here?

17:54 AWizzArd: sure

17:54 dakrone_hb: is there any good way to do profiling on a Clojure program for performance issues?

17:54 AWizzArd: also works very well in a remote setup, via slime-connect

17:54 duncanm: AWizzArd: how do you do the remote setup?

17:54 AWizzArd: dakrone_hb: just use your favourite Java profiler. For example the one in NetBeans.

17:54 duncanm: AWizzArd: i'm running Clojure-in-a-box right now

17:55 AWizzArd: duncanm: On the remote machine I have swank in my classpath. Then I log in there via ssh and run Clojure. Then I can (use 'swank.swank) and do something like (start-server "/dev/null" :port 4005)

17:55 djpowell: if you have a new-ish version of Java 6, there is a profiler built in called jvisualvm

17:55 I've found it to work quite well with clojure

17:56 AWizzArd: On my local machine I can oppen a ssh tunnel forwarding port 4005 and then M-x slime-connect <Enter> <Enter>, <Happy hacking>.

17:58 djpowell: yes, good idea. This jvisualvm works very well.

17:59 djpowell: it doesn't seem as heavyweight as most profilers i've used

17:59 usually if i have a performance problem, connecting a profiler slows things down so much i usually give up waiting for it

18:01 dakrone_hb: heh, takes Clojure 478 to do the same thing perl does in 54 seconds. Something must be terribly wrong with my code.

19:52 dnolen: I don't suppose there is an index-of anywhere in contrib is there?

20:08 cgrand: dnolen: .indexOf works on lists and vectors

20:09 dnolen: my java ignorance strikes again, thx cgrand.

20:13 gnuvince_: beware of nil though

20:13 ,(.indexOf nil "foo")

20:13 clojurebot: java.lang.NullPointerException

20:14 cgrand: true

20:14 Cark: ,(.indexOf :a ())

20:14 clojurebot: java.lang.IllegalArgumentException: No matching method found: indexOf for class clojure.lang.Keyword

20:15 Cark: ,(.indexOf () :a)

20:15 clojurebot: -1

20:34 dmiles_afk: hrrm CojureCLR.. was IKVM not possible?

20:34 well .. IKVM would probably work .. but the ClojureCLR to do a better job leveraging .NET?

20:35 * dmiles_afk is the DotLisp user and thinking about ussing ClojureCLR isntead

20:37 Chousuke: dmiles_afk: I think the best way to determine that is to give it a try.

20:43 dmiles_afk: i am about to.. actually if i have a question it'd be how close http://dotlisp.sourceforge.net/dotlisp.htm this is to clojure

20:43 scottj_: How do I get just the 10 from (re-find #"<foo>.+</foo>" "<foo>10</foo>")

20:44 Chouser: ,(second (re-find #"<foo>(.+)</foo>" "<foo>10</foo>"))

20:44 clojurebot: "10"

20:44 dmiles_afk: invoking static vs instance methods are under different syntax rules.. but about other things

20:44 SethTisue: "I'm not a Lisp expert."

20:45 - Rich Hickey

20:45 :-)

20:45 Chouser: SethTisue: that's an old quote, I would imagine.

20:45 scottj_: Chouser: thanks

20:45 SethTisue: 2003

20:45 dmiles_afk: invoking static vs instance methods are under different syntax rules = clojure use to be like this document .. but now differnt?

20:47 Chouser: dmiles_afk: I've never looked at dotlisp -- interesting similarities

20:47 SethTisue: it's interesting to learn that something like this was cooking that far back

20:47 dmiles_afk: i assumed it was the prototype

20:48 Chouser: dmiles_afk: the relevent clojure docs are here: http://clojure.org/java_interop

20:49 also interesting how long clojure did *not* have (.foo bar) syntax, and that it still doesn't allow x.y for member access

20:50 dmiles_afk: allot of why we are using DotLisp is even though w have a full Common Lisp on .NET .. we still too in love with the syntax simplicitty

20:51 Chouser: clearly some ideas came over, but Clojure's equality symantics, immutability, and concurrency support are fundamental and don't appear to have been in dotlisp

20:51 dmiles_afk: but since we havent written much lines of code yet.. it's early enough to switch to clojure

20:51 dreish: DotLisp doesn't have any of the persistent data structures or STM.

20:52 dmiles_afk: i mean wewritten 100s line s of code.. but not .dotlisp code ;P

20:52 Chouser: dotlisp has an early form of clojure seqs

20:52 hm, lazy seqs even -- maybe not so early

20:53 dmiles_afk: yeah all the lazy eval.. and them being default .. is what is so neat

20:53 dreish: Doesn't look like it has the clever ` either.

20:54 dmiles_afk: is cljure using , instead of ~ ?

20:54 dreish: No, still ~

20:54 Chouser: clojure on the jvm is a good deal more mature now than dotlisp was on clr. Not sure that any clojure on clr is up to snuff yet though.

20:54 * dmiles_afk noticed the botcmd

20:54 dreish: , is whitespace

20:54 clojurebot: java.lang.Exception: Unable to resolve symbol: is in this context

20:54 dreish: It's also clojurebot's sigil. ;)

20:54 Chouser: dreish is talking about the namespace-based hygine, I think.

20:54 dreish: Yes.

20:57 dmiles_afk: i run ABCL on .NET as a IKVM dll.. it makes the java interop become CLR interope very transparently.. maybe clojure might end up the same way oon IKVM

20:57 oon/on

20:57 so int = System.Int32

20:57 etc

21:06 ikvmc /development/clojure-read-only/clojure.jar built clojure.exe most excelently and it works!

21:09 user=> (.. System (getProperties) (get "java.vm.name")) ==> "IKVM.NET"

21:22 is 'set' == 'set!' ?

21:23 hiredman: no

21:23 ,(set (range 3)

21:23 clojurebot: EOF while reading

21:23 hiredman: ,(set (range 3))

21:23 clojurebot: #{0 1 2}

21:24 dmiles_afk: ok set is a creator of a set ;P

21:48 chessguy: ok, any enclojure users in the house? i'm working through http://enclojure.net/GettingStarted.html and got all the way to the end, but i don't have an option for "Clojure REPL Manager" to open the REPL

21:59 marklar: chessguy: I don't really use it, but I've installed it and it added just a "Clojure REPL" option under Window

22:02 Raynes: chessguy: Make sure you have the newest version of Enclojure. You can open an REPL by going to Window and clicking Create Standalone REPL and then entering the paths you want on your classpath including the path to clojure.jar and then clicking connect.

22:02 You can also create a project specific REPL by right clicking on your project and clicking Create Project REPL

22:02 Er, "Start Project REPL" actually. :)

22:07 chessguy: thanks guys, i'll play around with it more tomorrow

Logging service provided by n01se.net