我想在运行时完全生成一个fn(即名称和arg符号在运行时决定,而不是在代码中决定) 实现这一目标的最佳方法是什么?
例如,我如何实现以下功能?
(defn gen-fn [name arg-symbols body]
...
...
将像这样使用:
(gen-fn "my-func-name" (symbol "x") (symbol "y") (println "this is body. x=" x))
请注意,函数名称,args和body未编码,但可以在运行时决定
答案 0 :(得分:12)
(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)))
有些人使用:
user=> (gen-fn "foo" ["x"] '(do (println x) (println (inc x))))
#'user/foo
user=> (foo 5)
5
6
nil
但是,我并不喜欢这种方法。它闻起来很难闻:eval
。为什么要在运行时生成全局变量?我看到错误的命名空间和其他丑陋的打嗝出现在各种问题......
答案 1 :(得分:1)
另一种方法是使用“eval”和“read-string”:
用户=> (def f1(eval(read-string“(fn [x y](* x y))”)))
#'用户/ F1
用户=> (f1 3 5)
15
答案 2 :(得分:0)
我不完全确定,但我相信你可以使用一个优于eval的宏来做到这一点。
(defmacro gen-fn
[n as b]
(let [n (symbol n)
as (vec (map symbol as))]
`(intern *ns* n (fn ~n ~as ~@b))))