我正在努力理解闭包,但每个我能找到的关于闭包的定义都使用相同的晦涩和模糊的短语:“closes over(闭合)”。
什么是闭包?“哦,它是一个函数,closes over(闭合)另一个函数。”
但我找不到任何关于“closes over”(闭合)的定义。有人能解释一下“Thing A close over Thing B”是什么意思吗?
我正在努力理解闭包,但每个我能找到的关于闭包的定义都使用相同的晦涩和模糊的短语:“closes over(闭合)”。
什么是闭包?“哦,它是一个函数,closes over(闭合)另一个函数。”
但我找不到任何关于“closes over”(闭合)的定义。有人能解释一下“Thing A close over Thing B”是什么意思吗?
闭包是一个由代码指针和环境指针组成的对。环境指针包含了给定函数中的所有自由变量。例如:
fun f(a, b) =
let fun g(c, d) = a + b + c + d
in g end
val g = f(1, 2)
val result = g(3, 4) (*should be 10*)
函数g
包含两个自由变量:a
和b
。如果您不熟悉自由变量这个术语,它是指在函数范围内未定义的变量。在这种情况下,闭包意味着从函数中删除任何自由变量。上面的例子为闭包提供了很好的动机。当函数f
返回时,我们需要能够记住稍后使用的a
和b
的值。编译方式是将函数g
处理成一个代码指针和一个包含所有自由变量的记录,例如:
fun g(c, d, env) = env.a + env.b + c + d
fun f(a, b, env) = (g, {a = a, b = b})
val (g, gEnv) = f(1, 2)
val result = g(3, 4, gEnv)
当我们应用函数g
时,我们提供了调用函数f
时返回的环境。请注意,现在函数g
不再有任何未在其作用域中定义的变量。通常称不包含任何自由变量的术语为闭合。如果您仍不清楚,Matt Might 在http://matt.might.net/articles/closure-conversion/上有一个非常深入的闭包转换解释。
在闭包转换之前
function f(a, b){
function g(c, d) {
return a + b + c + d
}
return g
}
var g = f(1, 2)
var result = g(3, 4)
进行闭包转换后:
function g(c, d, env) {
return env.a + env.b + c + d
}
function f(a, b, env) {
return [g, {"a": a, "b": b}]
}
var [g, gEnv] = f(1, 2)
var result = g(3, 4, gEnv)
g
еҢ…еҗ«дёӨдёӘиҮӘз”ұеҸҳйҮҸпјҡa
е’Ңb
еҗ—пјҹдҪ еҲҡжүҚиҜҙиҝҮпјҢиҮӘз”ұеҸҳйҮҸжҳҜжҢҮеңЁдҪңз”Ёеҹҹдёӯ__жІЎжңү__е®ҡд№үзҡ„еҸҳйҮҸпјҹ - Sehnsuchtg
的主体内,参数a
和b
既没有作为参数传递,也没有在本地定义。这很符合Udacity的定义。 - Mattfun f(a, b, env) = (g, {a = a, b = b})
,对我来说毫无意义,也是最令人困惑的部分。有一个JS等效版本将有助于减轻语言的细节,并使该答案更容易被更多人理解。 - Vadorequestg
封闭了变量a
和b
。这种用法与How do JavaScript closures work?中的用法一致。这个回答是否在说,在“Before closure conversion”片段中没有封闭任何内容,但是在“After closure conversion”片段中却有封闭的内容?能否请澄清一下这个问题? - Sebastian Simon来自苹果文档
闭包是一种自包含的功能块,可以在代码中传递和使用。Swift 中的闭包类似于 C 和 Objective-C 中的块以及其他编程语言中的 Lambda 表达式。
但这意味着什么?
这意味着一个闭包可以捕获定义它的上下文中的变量和常量,并引用这些变量和常量,称为闭合这些变量和常量。
希望这有所帮助!