Clojure:如何绑定变量?

4

我在Clojure中定义了以下内容:

(def ax '(fn x [] (+ 1 z)))

(let [z 4]
    (str (eval ax))
)

但是不要返回:

5

我得到:

Unable to resolve symbol: z in this context 

我已经尝试将 "let" 更改为 "binding",但仍然无法正常工作。有人知道这里出了什么问题吗?

3个回答

11

尽可能地对你的代码进行最小化更改以使其能够工作:

(def ^:dynamic z nil)

(def ax '(fn x [] (+ 1 z)))

(binding [z 4]
    (str ((eval ax)))
)

这两个更改是将z定义为动态变量,以便名称解析,并在(eval ax)周围放置另一个括号,因为ax返回一个函数。

更好的方法是改变ax的定义:

(def ^:dynamic z nil)

(def ax '(+ 1 z))

(binding [z 4]
    (str (eval ax))
)

因此立即评估ax会得到所需的结果,而不是返回一个执行该操作的函数。

更好的方法是跳过eval:

(def ^:dynamic z nil)

(defn ax [] (+ 1 z))

(binding [z 5]
    (str (ax))
)

不过最好的方法是不将z作为变量四处飘荡,而是像Mimsbrunnr和Joost建议的那样将其传递给ax。


8
简短的回答是不要使用eval。你几乎从不需要它,当然也不需要在这里使用。
例如:
user> (defn ax [z]
         (+ 1 z))
#'user/ax
user> (let [f #(ax 4)]
         (f))
5

1

好的,我不太确定你在这里想要做什么。

我的意思是这个可以工作,虽然它没有使用 eval,而是将 x 定义为函数 (fn [ x ] (+ x 1))

> (def x #(+ 1 %))
#'sandbox102711/x
> (x 4)
5

最后,eval不是你应该使用的东西。作为Lisp Cljoure对lambda抽象和宏的支持(请参见上面的fn定义)应该消除这种需要。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接