2013-09-28 102 views
0

当我有下面的方法:红宝石参考

def n_times(thing) 
    lambda { |n| thing * n } 
end 

和我把它这样:

x = [:a] 
p1 = n_times(x) 
x = [:b] 
p p1.call(3) # => [:a, :a, :a] 

x将不被改变,输出将是[:A]。为什么?

在做这样的事情.pop实际上,X将被改变:

x = [:a] 
p1 = n_times(x) 
x.pop 
p p1.call(3) # => [] 

是因为[:B]是一个新的对象?

回答

1

这是因为x在第一种情况下被分配了一个新对象。您可以通过检查object_id

x = [:a] 
p x.object_id # => //some number 
p1 = n_times(x) 
x = [:b] 
p x.object_id # => //diff number 
p p1.call(3) # => [:a, :a, :a] 

x = [:a] 
p x.object_id # => //some number 
p1 = n_times(x) 
x.pop 
p x.object_id # => //same number 
p p1.call(3) # => [] 

# Another example 
x = [:a] 
p x.object_id # => //some number 
p1 = n_times(x) 
x[0] = :b 
p x.object_id # => //same number 
p p1.call(3) # => [:b, :b, :b] 
1

是因为[:b]是新对象吗?

是的。当你做x.pop时,你正在修改xthing所引用的对象。当你做x = [:b]时,你让x引用一个新的对象。创建变量引用新对象不会影响其他变量或对象。

请注意,如果lambda关闭了变量x,这将是另一回事。在这种情况下,更改x会影响lambda,但事实并非如此。 lambda关闭变量thing,这是一个不同的变量,它只是在重新分配x之前碰巧指向同一个对象。