How to convert list form to function in clojure

I have a function specification defined like this and I want to evaluate it in a function object so that I can pass.

(def spec '(foo [n] (* 2 n))) 

I can create such a macro

 (defmacro evspec [name arg & body] `(defn ~name [~arg] ~@body )) 

then the next call will give me the foo function. when called with 3, (foo 3) will return 6.

 (evspec foo n (* 2 n)) 

However, if I get the function body from my spec above, the function foo returns not to evaluate the shape of the body (* 2 n), instead it returns the shape of the body.

 (let [foo (first spec) arg (first (second spec)) body (last spec)] (evspec foo arg body)) user=> (foo 3) (* 2 n) 

I noticed that now the created function foo is equal to $ eval $ foo

 user=> foo #<user$eval766$foo__767 user$eval766$foo__767@39263b07 > 

while the working function is foo

 user=> foo #<user$foo user$foo@66cf7fda > 

can someone explain why the difference is and how can I make it work? I want to have a way without responding to eval? based on javascript background, I always think that eval is evil.

+4
source share
1 answer

It is simply impossible to do at all without eval . A macro is just a function that passes its expressions to arguments literally at compile time (when it is generally impossible to understand what their values ​​may be at run time). In particular, when evspec called inside the let form in the question text, where is the return value (* 2 n) , the evspec macro evspec literally sees the foo character and the n character as its positional arguments and (body) (seq containing the only body character) as its argument "rest"; the return value matches these inputs.

However, using eval for this kind of purpose is perfectly fine. It is important to keep in mind that it has a significant execution cost, so you will want to use it somewhat sparingly, but as soon as you create a function using eval , it works fine with the Clojure function, as fast as any other.

Also note that although JavaScript works with text in eval , Clojure eval works with Clojure data structures - indeed, the same data structure macros work, which may make it less error prone.

+4
source

Source: https://habr.com/ru/post/1490605/


All Articles