0

因此,如果我理解正确,Object#tap 使用 yield 来生成一个临时对象,以便在执行过程或方法期间使用。根据我对产量的了解,它做了类似的事情,产量需要(东西)并给(东西).dup到附加到它正在使用的方法的块?但是当我这样做时:

class Klass
attr_accessor :hash
  def initialize
   @hash={'key' => 'value'}
  end
end

instance=Klass.new
instance.instance_variable_get('@hash')[key] # => 'value', as it should

instance.instance_variable_get('@hash').tap {|pipe| pipe['key']=newvalue}

instance.instance_variable_get('@hash')[key] # => new value... wut?

我的印象是yield -> new_obj。我不知道这是多么正确,我试图在 ruby​​-doc 上查找它,但是 Enumerator::yielder 是空的,yield(proc) 不存在,并且纤维版本......我不有任何纤维,事实上,Ruby 不是明确要求包含“纤维”来使用它们吗?

所以应该是对实例变量的读取方法和对临时变量的写入,而不是对实例变量的读/写......这很酷,因为这就是我试图做的事情并且在我寻找时意外发现一种将哈希作为实例变量处理的方法(对于一些大于我习惯的用于命名变量数组的表),但现在我有点困惑,我找不到使这种情况发生的机制。

4

2 回答 2

2

Object#tap再简单不过了:

VALUE
rb_obj_tap(VALUE obj)
{
    rb_yield(obj);
    return obj;
}

(来自文档)。它只是产生然后返回接收器。IRB 中的快速检查显示yield产生对象本身而不是新对象。

def foo
  x = {}
  yield x
  x
end

foo { |y| y['key'] = :new_value }
# => {"key" => :new_value }

因此,正如我们所希望的那样, 的行为与tap一致。yield

于 2012-10-25T02:46:07.507 回答
0

tap不复制接收器。块变量被分配给接收者本身。然后,tap返回接收器。所以当你这样做时tap{|pipe| pipe['key']=newvalue},接收者会tap被修改。据我了解,

x.tap{|x| foo(x)}

相当于:

foo(x); x

y.tap{|y| y.bar}

相当于:

y.bar; y
于 2012-10-25T02:29:10.303 回答