【问题标题】:Eval with local bindings function具有本地绑定功能的评估
【发布时间】:2018-02-21 17:03:52
【问题描述】:

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

绑定序列的格式如下:([: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 通常是不好的做法。我不相信我可以把它写成一个宏,因为绑定和表达式只能在运行时给出,所以我要问的是:有没有更惯用的方法?

【问题讨论】:

  • 这纯粹是一种练习吗?我看不出这在现实世界中有什么用处。
  • “绑定和表达式只能在运行时给出”但为什么不直接编写 Clojure 并在运行时加载呢?这个问题似乎你可能会不必要地重新发明 Clojure 的一个子集。

标签: clojure


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2020-11-29
    • 2015-02-27
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    • 2021-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多