Julia作用域细节:在循环中定义闭包
我正在学习使用。他举了以下例子:Julia作用域细节:在循环中定义闭包,julia,Julia,我正在学习使用。他举了以下例子: anon = Array{Any}(undef, 2) for i = 1:2 anon[i] = () -> println(i) i += 1 end 现在调用此数组中的两个函数将输出: julia> anon[1](); anon[2]() 2 3 我不明白为什么输出是2,3而不是1,2。在第一次通过循环时,i=1,因此,anon[1]=()->println(1)。作者继续说: 这里,anon[1]和anon[2]都是匿名
anon = Array{Any}(undef, 2)
for i = 1:2
anon[i] = () -> println(i)
i += 1
end
现在调用此数组中的两个函数将输出:
julia> anon[1](); anon[2]()
2
3
我不明白为什么输出是2,3而不是1,2。在第一次通过循环时,i=1
,因此,anon[1]=()->println(1)
。作者继续说:
这里,anon[1]
和anon[2]
都是匿名函数。当他们
使用anon[1]()
和anon[2]()
调用,它们打印2
和3
(
i当它们被创建时加上1)
然后使用
let
实现预期的行为。然而,我在这个解释中缺少的是Julia作用域规则是如何运作的,以便产生2,3的第一个(意外)结果。换句话说,值2和3是如何得到的?有人能解释一下吗?谢谢 这相当棘手。你需要知道两件事:
- 在
循环变量for
中,每次迭代都会有一个新的绑定(我想你知道-我不知道Ivo的书,但从你的问题来看,我想这就是他在里面讨论的内容)i
- 在Julia中,闭包是通过创建一个对象来实现的,该对象从外部作用域捕获变量,然后可以访问它
anon[1]
已将循环第一次迭代中出现的i
绑定装箱。与第二个循环一样,i
的绑定是新的anon[2]
引用了这个新绑定
您甚至可以这样访问此内存位置:
julia> anon[1].i.contents = 100
100
julia> anon[1]()
100
甚至像这样(不推荐):
最后请注意,在循环的一次迭代中,将变量
i
赋值不会改变绑定(您正在写入相同的内存位置)。谢谢您的回答。我猜这里令人困惑的是,函数定义出现在循环中的时间早于I
的增加时间。我去了R,那里我比较熟悉,但那里的行为却很相似。也就是说,计数的是循环出口处的i
。此外,迭代器定义中的i
似乎与函数定义中的i
不同。第一个是{Any,1}
类型的数组,而前者是Int64
。我或多或少是对的吗?在循环I
中有一个类型为Int64
并指向内存中某个地址的变量。因此,在语句anon[i]
中,println(i)
和i+=1
变量i
在循环的一次迭代中引用了内存中完全相同的地址(尽管存储在该地址中的值会发生变化)。但是,对于每个循环,Julia都会为i
分配一个新的绑定,因此在每次迭代中i
都指向不同的内存位置。现在清楚了吗?
julia> anon[1].i.contents = 100
100
julia> anon[1]()
100
julia> for i = 1:2
anon[i] = () -> println(i)
anon[i].i.contents = 100 + i
i += 1
println(i)
end
102
103
julia> anon[1]()
102
julia> anon[2]()
103