4

这是我的简单测试代码:

def test_function
  0.tap do |v|
    v += 10
  end
end

p test_function

为什么我在这里得到 0 ?我在等10个。

更新:

class TestClass
    def initialize
        @v = 0
    end

    def inc 
        @v = @v + 1
    end
end

def test_function
    0.tap do |v|
        v += 10
    end
end

def test_function_2
    TestClass.new.tap { |obj|
        obj.inc
    }
end

p test_function
p test_function_2

0

测试类:0x29244f0 @v=1

4

2 回答 2

8

原因是原始对象没有被 += 操作符改变。那么在块中创建对它的引用,将引用更改为指向另一个对象,该对象大 10 然后返回,会发生什么情况。0 的值保持不变。

关于它的事情 - 这就是你想要发生的事情。+= 运算符不会更改它所操作的对象。它返回另一个不同的对象并将引用分配给它。这就像:

  v = 0
  v = v + 10

你不会期望0 == 10在这之后是真的,对吧?

于 2013-03-26T07:10:19.673 回答
4

这里还有其他答案:该方法tap返回原始对象。例如,您可以将其用于副作用,例如报告、收集统计数据或记录。它不会为您提供对原始对象的额外内部访问权限。

v = [0,1,2]
v.tap { |array| array.map { |x| x + 1 } }
=> [0,1,2]

v.tap { |array| array.map! { |x| x + 1 } }
=> [1,2,3]

可以使用您的 test_function_2 的变体,其中您控制的对象具有 Integer 属性,甚至只是具有一个元素的数组:

def test_function
  [0].tap do |v|
    v[0] += 10
  end
end

p test_function[0]
=> 10

. . . 取决于你想做什么?

于 2013-03-26T09:36:35.503 回答