以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
一样强大的绑定(与解构)?
答案 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
和函数参数解构创建了本地的,词法范围的绑定,因此解构的便利性不会导致名称污染。