Ruby for 结合 Proc 使用时的作用域问题

wilikeit · 2018年03月01日 · 最后由 wilikeit 回复于 2018年03月03日 · 1441 次阅读
a=[]
for i in ["hi","hello"]
    a<<Proc.new {i}
end

a.each do |m|
    puts m.call
end

输出: hello hello 怎么不是 hi、hello,何解?

运行时求值,拿到的是 i 的最终值,就是 hello 了。

另外,Ruby 中几乎从来不用 for 语句。

msg7086 回复

我的理解是在 each 中,每次循环时,Proc.new 创建的对象不同,而在 for 中 Proc.new 创建的始终是同 1 个对象,所以结果不同,可否这样理解?

wilikeit 回复

可以这么理解

for i in [1,2,3,4] do

end

puts i #=> 4

这里的 i 不是 local variable,实际上相当于定义了一个 i 变量,它的作用域和 for 同级。

但是下面的 i 就是 local variable,它的作用域不在 block 外

[1,2,3,4].each do |i|

end

puts i #=> NameError: undefined local variable or method `i' for main:Object

按照 SICP 的说法,因为 for 不会产生 frame,所以这里的所有 i 都属于同一个 frame,proc 求值时会从这个 frame 里找 i 的绑定,i 最后绑定的是 hello,结果自然就是两个 hello 了

a = []
for i in %w[hi hello]
    a << Proc.new { i }
end

i = 'magic'

a.each { |m| puts m.call }

楼主可以看看这个的执行结果

googya 回复

作用域在 ruby 中真是表现的淋漓尽致

misakamikoto 回复

绑定啊、frame 啊这些理解起来不直观,但貌似是那么回事

需要 登录 后方可回复, 如果你还没有账号请 注册新账号