eval performance

121 views
Skip to first unread message

Gabi

unread,
Dec 21, 2009, 2:32:55 PM12/21/09
to Clojure
Hi
I have this program that needs to do many eval's to same expression
(eval '(some-list-to-execut..))
My question is how can this be optimized ? Does eval compile the
evaled expression ? Does it re-compile the evaluated expression again
and again? Maybe I could compile the evaled expression once and
somehow eval the compiled bytcode?

rob

unread,
Dec 21, 2009, 4:22:03 PM12/21/09
to Clojure
It sounds like your use of evals might be something that could be done
better using a more idiomatic clojure approach. What are you trying
to do that re

rob

unread,
Dec 21, 2009, 4:22:14 PM12/21/09
to Clojure
It sounds like your use of evals might be something that could be done
better using a more idiomatic clojure approach. What are you trying
to do that re

On Dec 21, 2:32 pm, Gabi <bugspy...@gmail.com> wrote:

rob

unread,
Dec 21, 2009, 4:23:55 PM12/21/09
to Clojure
Sorry, I somehow accidentally sent it before I was done typing. The
rest of my sentence was "what are you trying to do thar requires the
use of evals in that way".

AlexK

unread,
Dec 21, 2009, 4:53:33 PM12/21/09
to Clojure
What eval does, is wrapping (fn* [] <expression>) around its
arguments, compiling that, and calling the resulting function object
(except if your list starts with a 'do or a 'def).

While Clojure's compiler is pretty fast, you should try not to use
eval. If you want to pass code around you should try something like
storing functions in a map or something similar.

If you think that you have to eval lists, try wrapping them in (fn
[] ...) and eval that form instead. You'll get a function object which
was compiled once, but can be called as many times as you want.

eg.

(defn form->fn [list-to-eval]
(eval (list 'fn [] list-to-eval))) ;this returns a fn

(def form->fn (memoize form->fn)) ;caches the resulting fns, beware of
memory leaks though

((form->fn '(println "Hello World")))
((form->fn '(println "Hello World")))
((form->fn '(println "Hello World"))) ; should compile only once

Alex

Gabi

unread,
Dec 21, 2009, 4:30:20 PM12/21/09
to Clojure
Experimenting with GeneticProgramming with Clojure..

Meikel Brandmeyer

unread,
Dec 21, 2009, 5:14:49 PM12/21/09
to clo...@googlegroups.com
Hi,

Am 21.12.2009 um 22:53 schrieb AlexK:

> (defn form->fn [list-to-eval]
> (eval (list 'fn [] list-to-eval))) ;this returns a fn

Please, make it a habit of writing even such simple code as `(fn [] list-to-eval) (or `(fn [] ~@list-to-eval) if list-to-eval is a Var or a local). If you make it a habit, you don't even come into the temptation to write broken macros.

Sincerely
Meikel

Gabi

unread,
Dec 21, 2009, 6:07:38 PM12/21/09
to Clojure
The problem with is that I need to execute the same function with
different bindings each time. So caching won't help me
For example I need to do something like:

(dotimes [_ 1000]
(intern 'user 'x (rand))
(eval '(prn (+(* x x) 5))))

On Dec 21, 11:53 pm, AlexK <alexander.konstanti...@informatik.haw-

kyle smith

unread,
Dec 21, 2009, 9:17:56 PM12/21/09
to Clojure
Here's the macro I used when I dabbled in Genetic Programming:

user> (time (dotimes [_ 1000]
(intern 'user 'x (rand))
(eval '(+ (* x x) 5))))
"Elapsed time: 425.754877 msecs"

user> (defmacro capture-vars [vars expr]
`(fn [~@vars] ~(first (next expr))))
#'user/capture-vars
user> (time (let [f (eval (capture-vars [x] '(+ (* x x) 5)))]
(dotimes [_ 1000000];note the iterations!
(f (rand)))))
"Elapsed time: 73.936157 msecs"

Graham Fawcett

unread,
Dec 21, 2009, 11:23:32 PM12/21/09
to clo...@googlegroups.com
On Mon, Dec 21, 2009 at 6:07 PM, Gabi <bugs...@gmail.com> wrote:
> The problem with is that I need to execute the same function with
> different bindings each time. So caching won't help me
> For example I need to do something like:
>
> (dotimes [_ 1000]
>  (intern  'user 'x (rand))
>  (eval '(prn (+(* x x) 5))))

So, 'x' is an open term within your expression. Simply define a
function (fn [x] (prn (+ (* x x) 5))) instead, and call it with your
binding for 'x'. No need for eval here -- maybe once to define the
function, but certainly not to evaluate the expression.

Best,
Graham

>
> On Dec 21, 11:53 pm, AlexK <alexander.konstanti...@informatik.haw-
> hamburg.de> wrote:
>> What eval does, is wrapping (fn* [] <expression>) around its
>> arguments, compiling that, and calling the resulting function object
>> (except if your list starts with a 'do or a 'def).
>>
>> While Clojure's compiler is pretty fast, you should try not to use
>> eval. If you want to pass code around you should try something like
>> storing functions in a map or something similar.
>>
>> If you think that you have to eval lists, try wrapping them in (fn
>> [] ...) and eval that form instead. You'll get a function object which
>> was compiled once, but can be called as many times as you want.
>>
>> eg.
>>
>> (defn form->fn [list-to-eval]
>>   (eval (list 'fn [] list-to-eval))) ;this returns a fn
>>
>> (def form->fn (memoize form->fn)) ;caches the resulting fns, beware of
>> memory leaks though
>>
>> ((form->fn '(println "Hello World")))
>> ((form->fn '(println "Hello World")))
>> ((form->fn '(println "Hello World"))) ; should compile only once
>>
>> Alex
>

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Gabi

unread,
Dec 22, 2009, 3:30:41 AM12/22/09
to Clojure
Superb!
This is exactly what I needed.. A way to get rid of the awkward intern
and boost performance.
Have you progressed far with your GP experimenting ?

kyle smith

unread,
Dec 22, 2009, 12:28:52 PM12/22/09
to Clojure
I haven't touched it in a while, but I'm going to pick it back up soon.

Brian Goslinga

unread,
Dec 23, 2009, 12:31:37 PM12/23/09
to Clojure
If you are doing GP, another approach to avoid using eval would be
using a tree of closures.

http://xach.livejournal.com/131456.html is an example of the technique
used in Common Lisp (should be similar enough).

Reply all
Reply to author
Forward
0 new messages