So if I understand correctly Object#tap uses yield to produce a temporary object to work with during the execution of a process or method. From what I think I know about yield, it does something like, yield takes (thing) and gives (thing).dup to the block attached to the method it’s being used in?
But when I do this:
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?
I was under the impression that yield -> new_obj. I don’t know how correct this is though, I tried to look it up on ruby-doc, but Enumerator::yielder is empty, yield(proc) isn’t there, and the fiber version… I don’t have any fibers, in fact, doesn’t Ruby actually explicitly require include ‘fiber’ to use them?
So what ought have been a read method on the instance variable and a write on the temp is instead a read/write on the instance variable… which is cool, because that’s what I was trying to do and accidentally found when I was looking up a way to deal with hashes as instance variables (for some larger-than-I’m-used-to tables for named arrays of variables), but now I’m slightly confused, and I can’t find a description of the mechanism that’s making this happen.
Object#tapcouldn’t be simpler:(from the documentation). It just yields and then returns the receiver. A quick check in IRB shows that
yieldyields the object itself rather than a new object.So the behavior of
tapis consistent withyield, as we would hope.