#clojure log - May 30 2008

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

7:02 cgrand: ozzilee: http://code.google.com/p/clj-stuff/wiki/TemplatingExamples#Javascript_HTML_templating_examples -- I'm not quite happy with the current version but it works for my actual needs

9:19 ozzilee: cgrand: I'm going to have to download that and take a look, looks quite cool.

9:20 I played with a templating system in Scheme that has some ideas I haven't seen elsewhere, you might be interested.

9:20 Look under "Templates": http://ozzilee.com/mettle/documentation/

9:21 cgrand: ozzilee: thanks, I'll look at it!

9:22 ozzilee: I also wrote some url-dispatching stuff in Clojure that's something like the Scheme code, but I don't have anything up anywhere.

9:23 Basically it lets you do (defpage ["foo" bar] (str "bar: " bar))

9:23 Which would print plaintext "bar: baz" at /foo/baz

9:26 cgrand: your templating system reminds me (because of the querying capabilities) of Genshi

9:30 ozzilee: I've never looked into Genshi, I'll take a look. Thanks!

9:30 cgrand: and I took the same road concerning url dispatch, see:

9:30 lisppaste8: cgrand pasted "defresource" at http://paste.lisp.org/display/61461

9:31 blackdog pasted "help with macro pls?" at http://paste.lisp.org/display/61462

9:31 blackdog: can't get my first macro to work :/

9:32 ozzilee: blackdog: Does the code the macro expands to work by itself?

9:32 blackdog: :/ didnt try that

9:33 ozzilee: That'd be your first stop.

9:34 blackdog: k

9:34 ozzilee: cgrand: What does :filters do?

9:34 Is that like middleware?

9:35 blackdog: same error, and i don't know why the string is expanded unquoted

9:35 lisppaste8: cgrand annotated #61462 with "actionPerformed" at http://paste.lisp.org/display/61462#1

9:37 rhickey: blackdog: does it work if you say: ~'actionPerformed

9:38 cgrand: similar to an around advice in AOP, here it allows me to set up the connection to the db

9:38 ozzilee: cgrand: Ah, ok.

9:39 cgrand: Do you use the jdk6 xmlwriter stuff?

9:40 blackdog: rhickey, thanks rich that works

9:40 rhickey: blackdog: great - I'll look into making that not necessary

9:40 blackdog: ok, so what i had should have workedt then?

9:40 i'm new to macros

9:41 rhickey: it has to do with how the proxy finds the matching names

9:42 cgrand: ozzilee: I had bad experiences with xmlwriter/reader for XHTML gen -- not enough control on the output (eg you have to hack around it to get to write a preamble which will trigger standard mode in most browsers)

9:43 ozzilee: cgrand: That's fine by me, I just don't have JDK6 :-)

9:56 Chouser: cgrand: you're referring to Java's own xml read/writer, or the code in clojure-contrib?

9:57 cgrand: chouser: java's Stax

10:10 ozzilee: Chart of Clojure's performance on a naive fibonacci function over last 70 or so revisions: http://groups.google.com/group/clojure/web/Fib.pdf

10:12 Single pass, so accuracy is probably crap, but it's a proof-of-concept.

10:14 rsynnott: not necessarily the best benchmark, as it's not a terribly optimisable problem

10:15 ozzilee: rsynnott: Again, proof-of-concept :-) The goal is an automated test that will alert us when a revision does something bad to performance.

10:16 Not so much for a benchmark. I intend to have a number of different performance tests.

10:16 Contributions weclome...

10:18 rsynnott: sbcl does something of this sort; you could steal their one :)

10:18 cgrand: chouser: I see xml-stream-writer.clj uses StAX. I'm trying to gather memories of what bit me: I think that is what related to round tripping the DTD.

10:18 ozzilee: rsynnott: I'll look into it, thanks.

10:19 * ozzilee knows nothing of the CL world

10:21 cgrand: ozzilee: interesting! Do you plan to include the benchmarks of the languages shootout?

10:23 Chouser: cgrand:

10:23 cgrand: ok. I don't know much about xml-stream-writer.clj

10:24 But I've been kicking around some ideas for xml representation, and thought it would be good to build on Java's libs

10:24 so if that's not true, I wanted to take note.

10:33 cgrand: chouser: ok. To back my claims: http://stax.codehaus.org/Extensions#Extensions-Rationale

10:40 rhickey: ozzilee: what's the time for this on your benchmark machine? :

10:40 (defn fib [n]

10:40 (if (int/< n 2) n (int/+ (fib (int/- n 1)) (fib (int/- n 2)))))

10:41 make sure you pass -server to Java for benchmarks of Clojure

10:49 ozzilee: 1020.345 msecs

10:49 for 35

10:50 rhickey: your chart was for 30, what's the apples-to-apples?

10:50 ozzilee: 30 is 490.813

10:50 Sorry, misremembered what the chart was for.

10:50 rhickey: if you run it a couple of times?

10:50 hotspot needs to warm up

10:51 on my machine the type-hinted version is 4x faster

10:52 51ms

10:52 drewr: 229, 236, 233 for me.

10:53 rhickey: drewr: vs what for the unhinted version (just drop the int/s)

10:53 ozzilee: Yeesh, yeah it gets down to 88.

10:53 Makes a big difference if you (defn fib ...) rather than ((fn fib ...) 30)

10:54 rhickey: yes, that's a must

10:54 jteo: bigints slow things down eh.

10:55 drewr: rhickey: 620 unhinted.

10:55 rhickey: polymorphic dispatch slows things down, and boxing

10:55 normally you shouldn't care, but having the hinted versions gives you tuning options when it matters

10:56 like on benchmarks :)

10:59 ozzilee: Hmm, actually it looks like I lied.

10:59 (defn fib [n]), then calling fib inside is the slowest.

10:59 (defn fib this [n]), then calling this inside is the same as (fn this [n])

11:00 Those both get down to 70, (defn fib [n]) stays at 382.

11:27 * drewr scratches his head at the Java library authors

11:30 drewr: java.text.ParseException: Unparseable date: "2008-04-09 17:00:07.403"

11:30 Are you kidding me? DateFormat doesn't understand a SQL Server timestamp?

11:30 No wonder people use .NET.

11:32 I'd love to write Clojure versions of these libraries and remove teh suck.

11:33 rhickey: http://www.swa.hpi.uni-potsdam.de/dls/dls08/

11:34 drewr: Nice!

11:35 rsynnott: I'm surprised SQL server doesn't just use standard SQL dates...

11:35 drewr: rsynnott: Is that not standard? That's the same as pgsql and mysql too.

11:36 rhickey: Impressive program committee.

11:36 rhickey: yeah

11:37 It's a very nice invite

11:46 rsynnott: mysql's one looks like '2008-05-30 17:15:04'

11:48 drewr: rsynnott: I wouldn't consider fractional seconds non-standard. Besides, there are no standards in RDBMSes. :-)

11:48 java.text.ParseException: Unparseable date: "2008-04-09 17:00:07"

11:49 java.text.ParseException: Unparseable date: "2008-04-09"

11:49 What alternate universe do they live in??

11:53 rhickey: drewr: are you using SimpleDateFormat?

11:54 drewr: rhickey: java.text.SimpleDateFormat@7945516e

11:54 rhickey: It has a ctor that takes a pattern

11:55 drewr: OK, I used the getDateTimeInstance factory.

11:55 But without a style.

11:57 Ah, I was using DateFormat.getDateTimeInstance() which apparently created my a SimpleDateFormat with no pattern.

12:12 rhickey: http://elw.bknr.net/2008/html/home.html

14:56 jteo: dumb qns: is there an equivalent to 'progn', or is there another way of doing things?

14:56 Chouser: (do ..) ?

14:58 jteo: ah. must have missed that in the documentation.

14:58 Chouser: np

16:33 Zilatica: anyone active in this page?

16:34 rhickey: yes

16:34 jgracin: sure

16:34 Zilatica: I'm taking a gander at clojure

16:34 and I just downloaded the ants.clj

16:34 trying to run it from the java command line

16:34 java -cp clojure.jar clojure.lang.Script ants.clj

16:35 is what I run

16:35 and for a split second, I see what looks like a pane pop up

16:35 and then immediately die

16:35 no logged exceptions to the prompt (that I see)

16:36 Chouser: try Repl instead of Script?

16:36 Zilatica: alright, will do

16:36 thanks!

16:36 rhickey: yes, and then run the commands in the comment section at the bottom

16:42 Zilatica: when running in Windows, what is the proper way to load a file from a fully qualified path? I've tried D:\research\ants.clj, which reported invalid token for \r, and I've tried D:/research/ants.clj, which reported invalid token, and I've tried just using a relative path from my command line call to invoke the reple (load-file "ants.clj")

16:43 jgracin: double prefix \\r

16:43 ?

16:43 guessing

16:43 Zilatica: just gave me an invalid token : D:

16:43 oddly enough

16:43 Chouser: file:// ?

16:43 also guessing.

16:43 what is this "Windows" of which you speak? ;-)

16:43 Zilatica: lol

16:44 rhickey: are you putting this inside " "?

16:44 Zilatica: one of the main reasons I got tired of dealing with lisp was I have to use windows at work and couldn't find a good way to involve it in the workplace

16:44 checking out clojure

16:44 cause I can get the repl to work on windows

16:44 yes

16:45 rhickey: I'd expect "D:\\research\\ants.clj" to work

16:45 also guessing

16:45 Zilatica: the full things I've tried: (load-file "D:/Development/Research/Clojure/ants.clj"), (load-file "D:\Development\Research\Clojure\ants.clj"), and (load-file "D:\\Development\\Research\\Clojure\\ants.clj")

16:45 sadly, none of those worked

16:45 Chouser: do you need the drive letter? If you're already on D: you could try "\\Development..."

16:46 jgracin: Zilatica: what does it report on using the "D:\\Devel..." variant?

16:47 Zilatica: user=> (load-file "D:\\Development\\Research\\Clojure\\ants.clj")

16:47 ")\n(load-file "

16:47 user=> java.lang.Exception: Invalid token: D:

16:47 java.lang.Exception: ReaderError:(5,1) Invalid token: D:

16:47 at clojure.lang.LispReader.read(LispReader.java:158)

16:47 at clojure.lang.Repl.main(Repl.java:68)

16:47 Caused by: java.lang.Exception: Invalid token: D:

16:47 at clojure.lang.LispReader.interpretToken(LispReader.java:224)

16:47 at clojure.lang.LispReader.read(LispReader.java:150)

16:47 ... 1 more

16:47 any ideas?

16:48 everyone hate windows? ;-)

16:48 rhickey: you may have cruft left from \\r, if you could, try restarting the repl and using the "D:\\research\\ants.clj" variant

16:48 Zilatica: as a side note, what is the command to quit the repl?

16:48 yes yes yes, total noob. I know.

16:49 tried quit, (quit), (exit), exit, sayoonara, (sayoonara)

16:49 and a handful of others

16:49 jgracin: try pressing CTRL-D

16:49 Zilatica: just get a ^D

16:49 hitting enter gets me nothing, repl still expecting input

16:49 rhickey: I think most of use do some variant of ^C on unix variants - there's no exit command, send whatever was EOF for DOS

16:50 ^Z ?

16:50 Zilatica: ctrl z works for the repl

16:50 until you run it in jline

16:50 then no bueno

16:51 * Chouser downloads clojure into a Windows virtualbox.

16:51 Zilatica: rhickey, you were right, the D:\\ variant worked after I quit the repl.

16:52 jgracin: (. System (exit 0)) should work.

16:52 rhickey: (. System exit 0)

16:52 Zilatica: The pane that showed up looks a bit funny though

16:52 just a pane with a blue square in the pane

16:52 not filled

16:52 looks like a width of 1 or 2

16:52 nothing really going in it

16:52 oh wait, hah, more commands to run

16:52 rhickey: that's right

16:52 Zilatica: sry, I'll read on!

16:53 rhickey: np

16:55 Chouser: hm, I can't even get "java" to work on Windows, so you're way ahead of me, Zilatica.

16:56 Zilatica: you're my new best friend.

16:56 :-)

16:56 nah, I just spent so much time trying to get lisp running on my mac that I gave up

16:56 couldn't get the emacs repl to work after 10 hours of investigation

16:57 and add to that the fact that work requires windows

16:57 just wasn't useful

16:57 now I have ants filling a pane with pheremones

16:57 very exciting

16:57 and all under 2 hours of investigation.

16:57 Chouser: :-)

16:58 Do I need to download my own JVM? Windows XP doesn't come with one?

16:58 Zilatica: yep

16:58 you checked out Eclipse.org?

16:59 that's where the action is for Java

17:01 rhickey: more perf boosts!

17:01 static public float[] vmul(float[] x, float[] ys){

17:01 final float[] xs = x.clone();

17:01 for(int i=0;i<xs.length;i++)

17:01 xs[i] *= ys[i];

17:01 return xs;

17:01 }

17:01 That's the Java for float/a*a

17:01 (defn amul2 [v1 v2]

17:01 (let [ret (float/aclone v1)]

17:02 (doidx i (float/alength v1)

17:02 (float/aset! ret (.get i)

17:02 (float/* (float/aget ret (.get i)) (float/aget v2 (.get i)))))

17:02 ret))

17:02 That Clojure runs at exactly the same speed

17:03 still working on making it easier, but the net result is no need to go to Java for low-level primitive array stuff

17:03 Zilatica: congrats?

17:03 Chouser: doidx is new?

17:04 rhickey: that's part of what I;m working on - it looks like I might need something like CL's symbol-macrolet

17:04 to get rid of the (.get i)

17:05 Chouser: symbol-macrolet provides a simple alternative to a code-walker or something?

17:05 rhickey: lets you bind a symbol to a replacement form

17:06 but yes, trying to do the same thing with a code walker is perilous

17:07 HotSpot is amazing - it turns all those function calls into the same code that uses primitives directly

17:07 Chouser: oh, so symbol-macrolet isn't itself just a code-walking macro? Where would such functionality be located -- the reader?

17:08 rhickey: I made several enhancements today to eliminate extra boxing to/from host calls

17:08 Chouser: ah, cool.

17:08 rhickey: Compiler, it's another form, like let

17:08 Chouser: oh, ok.

17:08 rhickey: not fun

17:09 it interacts (shadows/is shadowed by) with let

17:12 Chouser: yikes

17:13 rhickey: the other alternative is typed lets, but a much bigger can of worms

17:14 since Clojure still won't have primitive types or operations

17:14 and I don't want it to turn into Java

17:18 in a namespace, and with symbol-macrolet, it could look like:

17:18 (defn a*a [v1 v2]

17:18 (let [ret (aclone v1)]

17:18 (doidx i (alength v1)

17:18 (aset! ret i (* (aget ret i) (aget v2 i))))

17:18 ret))

17:20 Chouser: it would be trivial for i to be a fn, right? (aget ret (i)) isn't too bad

17:21 rhickey: to get these optimizations, it has to be a macro, not a fn

17:22 Chouser: and couldn't aget expect a fn instead of whatever it wants now, such that you'd be down to (aget ret i) without that sacry compiler work?

17:22 oh, ok.

17:23 rhickey: The ultimate goal:

17:23 (defn a*a [a1 a2]

17:23 (amap [i ret a1 a2]

17:23 (* (aget ret i) (aget v2 i))))

17:26 amap would be a macro that takes care of cloning and stepping

17:26 Chouser: and then you could rewrite float/a*a and all his friends in Clojure instead of Java?

17:27 rhickey: yup, and so could you or anyone write their own similar things, with performance the same as Java

17:27 Chouser: right

17:43 so hotspot doesn't inline functions well enough to rely on that instead of macros?

17:44 rhickey: It does, that's how this is all getting so fast - BUT, Clojure fns all take and return Object, and it doesn't eliminate the boxing

17:49 Chouser: does that mean (.get i) isn't a function call?

17:50 rhickey: It's a Java call, to a method on a type known to Clojure - those calls are all already as fast as Java and strongly typed

17:50 Clojure calls to Java methods are the same bytecode as Java calls to Java methods

17:51 So when I make a call to a Java function that does primitive math, Hotspot inlines it

17:51 Chouser: clojure calls to clojure functions don't require a method lookup, but do get all args boxed?

17:52 rhickey: yes, but they travel boxed all the time in Clojure, so no box/unbox except to go to the other side

17:52 Chouser: hm, ok.

17:53 rhickey: A clojure call is a call to a Java method that takes and returns Objects

17:53 But you can't define a fn that takes or returns an int, say

17:54 Chouser: thus ... symbol-macrolet.

17:54 rhickey: the last mile...

17:55 So, that's why there's Numbers.F.add etc

17:56 Chouser: would you be unhappy with special syntax for splicing a list, to simplify the interaction with let?

17:56 rhickey: ?

17:56 Chouser: I'm probably confusing the stages of evaluation.

17:57 (let [i '(.get 5)] (aget ret *i))

17:59 rhickey: yes, stages of evaluation is key

18:00 * rhickey running

18:00 Chouser: bye

18:09 Zilatica: is there a way to get closure to compile a clj into a jar?

18:09 I know it runs in a VM

18:10 but how about compiling clj into jars, does that work?

18:12 Chouser: you can include a .clj in a jar and load and run it from there

18:13 the clojure.jar itself includes several .clj files whose code is available at runtime.

18:14 Zilatica: ok, but if I inlcuded clojure.jar in an existing java project, could I run something in a Java class against a function defined in a clj?

18:15 Chouser: yes, though it requires a bit of setup, and then the call to the clojure function isn't just a "regular" Java call.

18:15 Zilatica: so cljs are interpreted, not compiled then?

18:15 Chouser: there are actually several options here, depending on what exactly you're trying to do.

18:15 cljs are compiled at runtime. Or something.

18:16 Zilatica: that "Or something." scares me. ;-)

18:16 basically, I'm just wanting to find out its capabilities

18:16 Chouser: that's just my ignorance. rhickey knows exactly what it does.

18:18 ericthorsen: if you define a user.clj in your application, the 1st call to a clojure RT function will look for that file and execute it

18:18 I use this for boot-strapping enclojure

18:18 This is built in to clojure

18:18 Chouser: ericthorsen: is that in the relased version?

18:19 ericthorsen: not sure...it is definitely up in svn and has been for a while now

18:19 Chouser: svn!?! I need to get that.

18:19 ericthorsen: it's very handy

18:20 Chouser: I'm trying to patch encojure to control the repl a bit differently, so that (hopefully) jVi will work with it. But I'm in over my head.

18:20 Zilatica: Chouser, what OS you running?

18:20 Chouser: Zilatica: there are several options. You can define clojure functions in a .clj and then call them by name from Java using a clojure library call.

18:21 Zilatica: Linux

18:21 ericthorsen: chouser: can you send me some details as to what you are up against there? We are doing quite a bit of work on enclojure and I'd like to see what happening there

18:21 Chouser: ericthorsen: absolutely! enclojure google group?

18:22 Zilatica: Chouser: I think I'm going to have to continue my investigation tonight, possibly tomorrow. About to head out of the office and into the wild. ;-)

18:22 thanks for the help!

18:22 and insight

18:22 * Zilatica pops his head up to see if the bosses are watching and begins to creep to the exit

18:28 ericthorsen: chouser: yes

Logging service provided by n01se.net