Hello everyone! It's great to be here with all you fellow Clojurians. Just so you know, this is my first post on this group, so don't shoot me if it's terrible ;)
As background, I've been working through SICP and have been loving Scheme. It's almost breathtaking how elegant and clean the code can be (I had some moments like xkcd goes off abou <http://xkcd.com/224/>t). Of course, though Scheme is beautiful and simple, everyone knows that it's not especially practical, in general. I love the Lisp paradigms but I'm not really a fan of CL so I did some looking around and stumbled upon Clojure. It seems that Clojure really has a lot going for it between shockingly easy concurrency support and Java interop, among other things. But one thing that's been bothering me is that it seems like to optimize performance in Clojure, you have to sacrifice some elegance. *Example 1: Tail-call recursion* *Scheme* One example would be tail-call recursion. For instance, normally in Scheme I'd naively implement an iterative exponent function like this: (define (expt x n) (cond ((= 0 n) 1) ((= 1 n) x) (else (expt (* x x) (- n 1))))) Pure. Simple. Beautiful. (Not that I'm the best Scheme programmer ever, but to me it looks beautiful, and it conforms well to the base of the problem. You get the point.) *Clojure* Of course, tail-call recursion is not possible with JVM, so Clojure uses a * recur* macro in place of direct recursive function calling. It avoids blowing the stack as quickly but it's still not 100% "mathematically pure" in the way Scheme tends to be. An added gripe is that the* else *form within *cond *in Clojure uses a keyword, *:else*, instead of the more consistent parenthetical form used in Scheme. I suppose that's to make it less "Lispy." But it just ends up making it a little less elegant. *Example 2: Type casting* * * Some have said that Clojure can be somewhat slow (as with all Lisps). I'm not sure how true this is, but I stumbled on an example on John Lawrence Aspden's blog<http://www.learningclojure.com/2013/02/clojure-is-fast-is-clojure-still-fast.html>. He wrote a program to implement Euler's method like so: *First Solution* (defn f [t y] (- t y)) (defn solveit [t0 y0 h its] (if (> its 0) (let [t1 (+ t0 h) y1 (+ y0 (* h (f t0 y0)))] (recur t1 y1 h (dec its))) [t0 y0 h its])) He points out that "if this was an assembly language program that worked the way you'd expect, each loop would take 7 cycles." So he tests it for Clojure. The result? On his netbook with Clojure 1.4: 2400 cycles. As he says, "We're looking at a slowdown of about 300 times over what we could probably achieve coding in assembler or in C with a good optimizing compiler." That's not surprising, I suppose, but it's still a little disheartening. After all, you want your language to be fast, right? Well, after a few iterations, he manages to reduce the cycles way down - all the way down, in fact, to 37, which is quite a feat. Like so: *Final Solution* (defn solveit-4 [t0 y0 h its] (let [zero (long 0)] (loop [t0 (double t0) y0 (double y0) h (double h) its (long its)] (if (> its zero) (let [t1 (+ t0 h) y1 (+ y0 (* h (- t0 y0)))] (recur t1 y1 h (dec its))) [t0 y0 h its])))) But the thing is, between the *recur *macro, explicit typecasting, and the *loop* construct, yes, you have a very significant performance increase, but it the code's gotten bigger, much less readable, and much less elegant. *The bottom line* * * My idea, which is probably very naive, but one which I'm curious about, is: *Is it possible to have some sort of set of automatic-optimizing macros that work on Clojure code to preserve elegance while maximizing performance?* * * In theory, it would be kind of an abstraction layer. There would be one file that would store the code that gets read and another output file that stores the code that actually gets evaluated by the REPL, and a set of macros to optimize the "front-end", "abstracted" file into the output, "nuts-and-bolts" file to be evaluated by the REPL. Probably this would be a very intensive process - I don't know. But maybe it's worth the trouble after all to save a ton of programmer-hours by increasing readability. Thoughts? -- -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.