GabiMe
GabiMe

Reputation: 18473

Clojure: How to create a function at runtime

I want to generate a fn totally at runtime (i.e. the name and the arg symbols are decided at runtime, not in code) What's the best way to achieve this ?

For example how can I implement the following function ?

(defn gen-fn [name arg-symbols body]
...
...

which would be used like this:

(gen-fn "my-func-name" (symbol "x") (symbol "y") (println "this is body. x=" x))

Note that function name, the args and the body are not coded but can be decided at runtime

Upvotes: 7

Views: 1926

Answers (3)

jamesqiu
jamesqiu

Reputation: 1704

Another way is using "eval" and "read-string":

user=> (def f1 (eval (read-string "(fn [x y] (* x y))")))

#'user/f1

user=> (f1 3 5)

15

Upvotes: 1

Jeremy Wall
Jeremy Wall

Reputation: 25237

I'm not entirely sure but I believe you could do this with a macro which would be superior to eval.

(defmacro gen-fn
  [n as b]
  (let [n  (symbol n)
        as (vec (map symbol as))]
    `(intern *ns* n (fn ~n ~as ~@b))))

Upvotes: 0

kotarak
kotarak

Reputation: 17299

(defn gen-fn
  [n as b]
  (let [n        (symbol n)
        as       (vec (map symbol as))
        fn-value (eval `(fn ~n ~as ~b))]
    (intern *ns* n fn-value)))

And some use:

user=> (gen-fn "foo" ["x"] '(do (println x) (println (inc x))))
#'user/foo
user=> (foo 5)
5
6
nil

However, I don't really like this approach. It smells really hard: eval. Why do you want to generate globals at runtime? I see various problems with wrong namespaces and other ugly hiccups rising at the horizon...

Upvotes: 12

Related Questions