为什么没有以def形式进行破坏?

时间:2011-11-19 21:03:48

标签: clojure lisp let function destructuring

let形式(此处为Clojure)我可以做类似

的事情
(let [[u s v] (svd A)] 
   (do-something-with u v))

其中svd返回长度为3的列表。这是一件非常自然的事情,为什么我们不这样做呢?

(def [u s v] (svd A))

及其各种概括作为def表单的默认行为?我不知道这会如何干扰def已经在做的任何事情。理解Lisp或Clojure的Zen的人能否解释为什么def不支持与let一样强大的绑定(与解构)?

3 个答案:

答案 0 :(得分:16)

def是编译器级别的一种特殊形式:它构成一个Var。在解构可用之前,def必须可用且可用。你会看到与let*类似的东西,一个不支持解构的编译器原语:然后在clojure/core.clj中的几千行后,语言最终足够强大,可以提供带有解构的let版本,如let*之上的宏。

如果您愿意,可以编写一个宏(例如,def+)来为您执行此操作。就个人而言,我认为它有点粗暴,不会使用它,但使用Lisp意味着使用适合您个人的语言。

答案 1 :(得分:2)

def基本上是Vars的构造函数。第一个参数是命名Var的符号。它接受该符号并返回该符号的Var。解构会改变这些语义。

但是你可以写一个宏来做它。

答案 2 :(得分:1)

以下是一些哲学上的理由。

Clojure支持变异性的不变性,应该仔细考虑和命名所有可变性来源。 def创建了可变的变量。因此,惯用语Clojure都不会使用它们,并且也不希望它太容易创建许多可变的变量而无需小心(例如通过解构)。然而,let和函数参数解构会创建不可变的绑定,因此Clojure使这些绑定很容易创建。

def创建的变种具有全局范围。因此,您应该仔细命名def ed vars并保留少量数据。解构def会让您轻松创建许多def而无需谨慎。另一方面,let和函数参数解构创建了本地的,词法范围的绑定,因此解构的便利性不会导致名称污染。