0

我试图在 Clojure 中实现这个逻辑(只是一个例子):

a = 1 + 5
b = a + 3
c = a + 4
d = c + a
return f(a, b, c, d) 

到目前为止,我设法编写的最好的代码如下所示:

(let [a (+ 1 5) b (+ a 3) c (+ a 4) d (+ c a)] (f a b c d))

这看起来相当麻烦,主要是因为在我的实际案例中,这些“添加”操作要复杂得多,可能需要几行代码。我宁愿把它写成(Lisp 风格):

(set a (+ 1 5))
(set b (+ a 3))
(set c (+ a 4))
(set d (+ c a))
(f a b c d)

在 Clojure 中可以吗?

4

3 回答 3

4

实际上,您几乎在 Clojure 中找到了最好的解决方案:

(let [a (+ 1 5)
      b (+ a 3)
      c (+ a 4)
      d (+ c a)]
  (f a b c d))

您不能以命令式风格编写 Clojure 代码,因为它是一种函数式语言。你也不能随意使用 defs,因为 Clojure 中的所有变量都是不可变的。所以,那些定义的不能改变。所以,如果你想临时绑定一些变量,你应该使用let.

于 2013-05-24T20:39:10.450 回答
4

不,这是有意的,因为(set ...)您所描述的调用暗示以 Java 和 C# 等语言的方式使用可变状态。这是 Clojure 积极避免的事情,以便以更理智的方式管理状态,这在并发中真正变得重要。如需更多信息,请访问 Clojure 网站

此外,let表单并不繁琐,它是一个有用的范围界定工具:在您的示例abcd都是本地的。这意味着一旦指令指针跳出 let,所有这些绑定都会被遗忘。

相反,即使您的(set...)示例能够正常工作,您也会用所有这些短暂的名称污染您的命名空间。

于 2013-05-24T20:26:10.280 回答
3

Clojure 中的set 函数从另一个集合容器创建一个集合数据类型,而不是改变变量的值。但是,您可以执行以下操作:

(def a (+ 1 5))
(def b (+ a 3))
(def c (+ a 4))
(def d (+ c a))
(f a b c d)

alet 语句允许您做同样的事情,但不会使用、bcd值“污染”您的顶级命名空间。但是,如果您希望能够坚持并参考abcd, adef就可以了。

于 2013-05-24T20:40:23.400 回答