On Dec 21, 2:32 pm, Gabi <bugspy...@gmail.com> wrote:
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
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
(dotimes [_ 1000]
(intern 'user 'x (rand))
(eval '(prn (+(* x x) 5))))
On Dec 21, 11:53 pm, AlexK <alexander.konstanti...@informatik.haw-
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"
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
http://xach.livejournal.com/131456.html is an example of the technique
used in Common Lisp (should be similar enough).