我是Clojure的新手,我读到它是一种功能语言。它说Clojure没有变量,当我找到(def n 5)时,它和变量之间有什么区别?
我之后可以更改var的值,那么它与变量真的有什么不同吗?我不明白其中的区别。
答案 0 :(得分:5)
假设variable
表示引用可变存储位置,我猜主要区别(取决于您比较哪种语言),如果您动态重新绑定{{ Clojure中的1}}是基于每个线程的。
但是答案很长,你通常不会在Clojure中使用var
,除非你真的需要引用可变存储位置。
Clojure使用值而不是引用来支持不变性和编程。
您可以观看有关值的Rich Hickey's talk。
总结一下,当您在Clojure中编程时,您所拥有的是值,而不是对可能发生变化的位置的引用(甚至可能由另一个线程更改)。
所以
var
即使您在该代码中得到“更改(let [a 1
_ (println a) => prints 1
a 2
_ (println a) => prints 2
])
”的错觉,您也不会更改“旧”a
您只有一个新值。 (如果有人看过第一个定义,它仍会看到值1)。
实际上,你可以看到作为组合函数的赋值序列调用范围中a
被替换的地方,但根本不是相同的“变量”。
a
尽管如此,如果您需要一个可变存储,可能有许多线程访问该存储,Clojure gives you ((fn [a]
(println a) => prints 1
((fn [a]
(println a) => prints 2
) 2) 1)
,vars
,atoms
等等。
答案 1 :(得分:2)
Clojure没有变量,这是不正确的。即多变的参考文献。但是,它们不能用于存储和查找可以建模为纯数学函数的计算。
不变性的概念是处理具体的价值而不是一个或其他人可以改变的参考。就像1
是一个你无法改变的值一样,在Clojure中,向量[3 2]
是你也无法改变的值。 E. g。如果你的算法需要将1
附加到该向量,它需要创建一个新的向量,保留原有的向量,而在命令式语言中,你可以“改变”向量,打破可能依赖它的一切。不可变性的取处在于您不必再担心这一点,并且您的代码变得不那么容易出错。
Clojure以一种新创建的值有效地重用它们所基于的值的大多数内存的方式实现不可变数据结构。它们提供与用于读写的可变对应物(即创建新版本)几乎相同的性能特征。您可能希望详细了解here,Rich Hickey在与Brian Beckmann的this对话中做了一些很好的解释。
答案 2 :(得分:0)
将 def 视为定义常量。可以通过再次调用 def 来更改,但是should not do it。
变量的关闭是agents,它们是线程安全的。
(def counter (agent 0))
(send counter inc)
@counter
;;=> 1
您还可以在Java类中访问该变量。
新课
(def object (ClassName.))
Se值
(.fieldName object)
设定值
(set! (.fieldName object) 5)
"整体"没有变量的一点是使程序自动线程安全。这是因为线程错误将始终"总是"在该线程失败1将告诉变量 a 是1并且线程b告诉 a 是2并且在此之后失败。这也是使用纯函数的原因 - 没有变量" no"线程问题。
另请参阅此question:Clojure differences between Ref, Var, Agent, Atom, with examples和此Clojure: vars, atoms, and refs (oh my)。
治疗""如80%或更多 - 不是100%。