事实上,很多人都感到困惑,包括您所链接问题的答案中的一些人。
让我重申一下我的回答:lambda 是一种语言构造,用于(匿名)函数表达式,闭包是一种实现技术,用于使本地函数成为一流的。
例如,在函数式语言中,命名函数定义
f x = x + 1 (* 1 *)
通常只是 lambda 表达式的简写:
f = lambda x => x + 1 (* 2 *)
(反之亦然,lambda 可以看作是辅助局部定义的简写,例如,
lambda x => x + 1
相当于一个 let 表达式:
let f x = x + 1 in f
)
换句话说,lambda 只是语法,它们本身并不暗示任何语义。
另一方面,闭包是一种实现局部函数的方法,无论是表示为 lambda 还是以命名形式。例如,考虑:
g x = let h y = x + y in h (* 3 *)
或等效:
g x = lambda y => x + y (* 4 *)
(函数式语言甚至允许将后者缩写为
g x y = x + y
)
这里的内部函数引用了外部函数的一个局部变量(参数x)。像g 2 这样的表达式会返回一个函数,但是这个函数的内部表示不能仅仅由h 的“代码”组成,它还必须包含x = 2 的信息。后者称为闭包环境,闭包环境和“代码”这对就是所谓的“闭包”。这个名字来自数学:一个函数对象“关闭”它的环境(来自外部范围的名称),在一个自包含实体的意义上。在实现中,这很重要,以便即使在周围的调用早已返回时,这些函数也能作为独立值持久存在。
所以,如您所见,有些函数写成 lambda(例如上面的 2 和 4),有些函数必须表示为闭包(例如,上面的 3 和 4),但也有可能发生没有另一个(例如,2 或 3)。 (尽管具有一等函数的语言通常将所有函数都视为闭包,但在退化的情况下,它们只是有一个空的闭包环境。)
人们经常混淆这两个概念的原因是许多主流语言没有正确的局部函数概念,可以不受限制地引用局部变量(即它们没有闭包)。然后一些人开始引入 lambda 表达式作为局部函数的 only 适当形式。为了更清楚地说明差异,人们明确地谈论“闭包”,以区别于其他残缺形式的局部函数,就像它们以前存在于一些主流语言中一样。