Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 381
GabiMe Avatar asked Dec 01 '09 09:12

GabiMe


2 Answers

(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...

like image 52
kotarak Avatar answered Nov 08 '22 13:11

kotarak


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

like image 35
jamesqiu Avatar answered Nov 08 '22 14:11

jamesqiu