I've just released Vertigo [1], which I describe in this 
thread: https://groups.google.com/forum/#!topic/clojure/BayfuaqMzvs.  I 
suspect this has some bearing on the conversation.

Zach

[1] https://github.com/ztellman/vertigo

On Tuesday, July 9, 2013 8:11:58 AM UTC-7, Alexander Gunnarson wrote:
>
> 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.


Reply via email to