我运行一个简单的函数:
def test
a = 10
yield a
puts a
end
test { |x| x += 10 }
并得到意想不到的答案
> 10
接下来,我尝试以这种方式重用该功能:
def test
a = 10
a = yield a
puts a
end
结果是
> 20
但是我发现这段代码很难看,而且不是红宝石式的,我怎么能改进呢?
答案 0 :(得分:3)
在红宝石中,一切都是参考。这是什么意思?您使用的每一位数据(如数字10或字符串' hello world')都会在内存中的某处创建。并且所有变量(也放在内存中)只是指向那些对象占用的内存位置。
有两种类型的对象 - 可变和不可变。可以修改可变对象,即如果我们有一个字符串'你好'放在内存中,我们可以修改它而不改变它在内存中的位置,因此指向其位置的所有其他变量也将产生更改的值。例如:
a = b = 'hello'
a[2] = 'b'
a #=> 'heblo'
b #=> 'heblo'
所以你创造了'你好''内存中的字符串对象,并将变量a和b指向其内存位置。现在,如果你修改它,因为两个变量都指向同一个位置,所以两个变量似乎都被改变了。然而,新价值的确定
a = 'foo'
b #=> 'heblo'
不修改对象。它是在内存中创建一个新对象,并将变量b指向该对象的内存位置。另请注意:
a = 'foo'
b = 'foo'
将在内存中创建两个单独的对象,变量a和b指向不同的位置。
不可变对象无法修改且无法复制。这意味着存储器中最多总有一个位置代表给定对象。例如,所有Fixnums都是不可变的(也是nil,false,true和symbols)。因此这段代码:
a = 1
b = 1
将使两个变量都指向内存中的相同位置。它并不重要,因为存储在那里的对象无论如何都无法修改。
那么当你将一个变量输入一个块时会发生什么。创建新变量以指向内存中的相同位置。由于您正在产生一个fixnum,whcih是不可变的,因此无法修改。所以'x + = 10'实际上将新的局部变量x重新分配到内存中的不同位置,因此原始x不会改变。
如果你传递一个字符串并修改它会有所不同:
def test
a = 'foo'
yield a
puts a
end
test { a.replace 'bar' }
# Output: 'bar'
注意replace
方法修改字符串而不重新指定内存指针。
答案 1 :(得分:2)
说你有这个功能:
def test(x)
x += 10
end
如果我有:
a = 10
test(a)
a
不会改变。因此,在您的示例中,a
在块执行后仍为10。
如果有的话,你可以这样做:
def test
puts yield 10
end
答案 2 :(得分:1)