带有本地绑定功能的Eval

时间:2018-02-21 17:03:53

标签: clojure

我正在尝试编写一个函数,它接受一系列绑定和一个表达式并返回结果。

绑定序列的格式如下:([:bind-type [bind-vec] ... )其中bind-type是let或letfn。例如:

([:let [a 10 b 20]] [:letfn [(foo [x] (inc x))]] ... )

表达式只是一个常规的Clojure表达式,例如(foo (+ a b))所以这个示例输入对将是31个。

目前我有这个:

(defn wrap-bindings
  [[[bind-type bind-vec :as binding] & rest] expr]
  (if binding
    (let [bind-op (case bind-type :let 'let* :letfn 'letfn*)]
      `(~bind-op ~bind-vec ~(wrap-bindings rest expr)))
    expr))

(defn eval-with-bindings
  ([bindings expr]
   (eval (wrap-bindings bindings expr))))

我对Clojure不是很有经验,并且被告知使用eval通常是不好的做法。我不相信我可以把它写成宏,因为绑定和表达式可能只在运行时给出,所以我要问的是:有没有更惯用的方法呢?

1 个答案:

答案 0 :(得分:2)

eval 几乎总是不是答案,尽管有时会发生罕见的事情。在这种情况下,您符合条件,因为:

  

因为绑定和表达式只能在运行时给出

  • 您希望在程序运行时输入和运行任意代码
  • 要使用的绑定表单可以输入任何数据,甚至是程序中其他地方的数据

因此,至少在我理解问题的情况下,使用eval的现有示例是适当的。也许有空间可以改变要求以允许提前定义表达式并消除对eval的需求,但如果没有,那么我建议使用你拥有的。