在你所提到的上下文中,可以将闭包看作是引用其外部作用域中定义的某些变量的函数(对于其他情况,请参见 @phipsgabler 的答案)。以下是一个最简示例:
julia> function est_mean(x)
function fun(m)
return m - mean(x)
end
val = find_zero(fun, 0.0)
@show val, mean(x)
return fun
end
est_mean (generic function with 1 method)
julia> x = rand(10)
10-element Vector{Float64}:
0.6699650145575134
0.8208379672036165
0.4299946498764684
0.1321653923513042
0.5552854476018734
0.8729613266067378
0.5423030870674236
0.15751882823315777
0.4227087678654101
0.8594042895489912
julia> fun = est_mean(x)
(val, mean(x)) = (0.5463144770912497, 0.5463144770912497)
fun (generic function with 1 method)
julia> dump(fun)
fun (function of type var"#fun#3"{Vector{Float64}})
x: Array{Float64}((10,)) [0.6699650145575134, 0.8208379672036165, 0.4299946498764684, 0.1321653923513042, 0.5552854476018734, 0.8729613266067378, 0.5423030870674236, 0.15751882823315777, 0.4227087678654101, 0.8594042895489912]
julia> fun.x
10-element Vector{Float64}:
0.6699650145575134
0.8208379672036165
0.4299946498764684
0.1321653923513042
0.5552854476018734
0.8729613266067378
0.5423030870674236
0.15751882823315777
0.4227087678654101
0.8594042895489912
julia> fun(10)
9.453685522908751
如您所见,
fun
持有对外部作用域(在本例中由
est_mean
函数引入的作用域)变量
x
的引用。而且,我已经向您展示了,即使从
fun
外部检索此值作为其字段(通常不建议这样做,但我向您展示了这一点,以证明确实
fun
存储对其外部作用域定义的对象
x
的引用;它需要存储此引用,因为变量
x
在
fun
函数体内部使用)。
在估计的上下文中,正如您所指出的那样,这是有用的,因为在我的情况下,find_zero
要求函数仅采用一个参数 - 在我的情况下是 m
变量,而您希望返回值取决于传递的 m
和 x
。
重要的是,一旦 x
被捕获在 fun
闭包中,它就不必在当前作用域中。例如,当我调用 fun(10)
时,代码会正确执行,尽管我们在 est_mean
函数的作用域之外。但这不是问题,因为 fun
函数已经捕获了 x
变量。
让我再举一个例子:
julia> function gen()
x = []
return v -> push!(x, v)
end
gen (generic function with 1 method)
julia> fun2 = gen()
julia> fun2.x
Any[]
julia> fun2(1)
1-element Vector{Any}:
1
julia> fun2.x
1-element Vector{Any}:
1
julia> fun2(100)
2-element Vector{Any}:
1
100
julia> fun2.x
2-element Vector{Any}:
1
100
在这里,你可以看到在gen
函数内定义的x
变量被匿名函数v -> push!(x, v)
捕获,并且将其绑定到fun2
变量上。稍后,当你调用fun2
时,x
变量绑定的对象得到更新(并且可以被引用),尽管它是在gen
函数范围内定义的。即使我们离开了gen
的作用域,由匿名函数捕获的绑定到x
变量的对象仍然存在,因为我们定义了这个匿名函数。
如果有不清楚的地方,请评论说明。