我正在尝试根据一个已评估函数的结果和一系列其他函数的结果构建一个函数。如果我部分构建它,它工作正常,但每次我尝试构建整个东西时,它都会失败。
(defn play []
(let [eval1 (eval '(+ 1 1))]
(eval `(->> ~eval1 (+ 5) (- 2) (* 7)))
)
)
这失败了:
(defn play []
(let [eval1 (eval '(+ 1 1))
eval2 '((+ 5) (- 2) (* 7))]
(eval (cons (cons eval1 eval2) ->>))
)
)
我尝试了许多其他方法将其组合在一起,我认为这归结为我不太理解 clojure 的这方面。解决这个问题的最佳方法是什么?谢谢!
最佳答案
You generally don't want to use eval
。然而,也许这次您会这样做,无论出于什么原因(了解 Clojure 的阅读器是一个有效的原因)。因此,答案取决于您所说的“这个问题”的含义。
第 1 部分——评估
A.韦伯的answer完全没问题。如果您提供的示例只是为了让您了解 Clojure 阅读器的工作原理,那么我回答的其余部分可能与您无关。
第 2 部分 - 无需评估
如果“这个问题”是指从函数列表和值构造一个函数,那么您不需要eval
。将 (eval '(+ 1 1))
替换为 (+ 1 1)
。然后因为你想要一个函数列表,你可以使用 #(+ 5 %)
等或 (partial + 5)
等等并将它们存储在列表中。
->>
是一个线程宏。这意味着它在编译时执行,以转换其整个 S 表达式。但在失败的代码中,它在编译时没有 S 表达式 - 您将尝试通过 cons
ing 在运行时构建其 S 表达式将其添加到另一个列表中。
您可以编写另一个宏来执行您想要的操作。但一般来说,当我遇到将函数列表应用于初始值的问题时,我使用 reduce :
(defn play []
(let [eval1 (+ 1 1)
eval2 (list #(+ 5 %) #(- 2 %) #(* 7 %))]
(reduce #(%2 %) eval1 eval2)))
事实上,这在我的代码中经常出现,以至于我的大多数项目的 core.clj 中都有这样的内容:
(defn freduce
"Given an initial input and a collection of functions (f1,..,fn),
This is logically equivalent to ((comp fn ... f1) input)."
[in fs]
(reduce #(%2 %) in fs))
最后,如果您想要构造一个函数而不是其求值,则用 fn
包装返回值:
(defn play []
(let [in (+ 1 1)
fs (list #(+ 5 %) #(- 2 %) #(* 7 %))]
(fn [] (freduce in fs))))
user=> ((play))
-35
关于function - 如何从函数列表和值构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22765051/