How to pass the current binding’s block to some other method?
I’ve posted this question to the mailing list but I might as well ask it here too, in case any of my three or four readers know the answer. Suppose I have a method that will yield to a block if one is given:
def try(x, y, z)
# ... do some other stuff first ...
yield self if block_given?
end
Such that you can call it like so:
obj.try(1, 2, 3) { |recv| ... do something with recv ... }
Now suppose that I create an alias to this method, for the purpose of overriding how it’s called, e.g.
alias old_try try
def try(hash)
old_try(hash[:x], hash[:y], hash[:z])
end
If someone calls this new and improved version of try and provides a block, is there any way for me to somehow pass that block down into oldtry without actually modifying the method signature for oldtry? I had thought maybe there was some trickery I could do with the binding for the “outer” method call (i.e. the one to the new version of try) but that doesn’t appear to be the case.
I could be misinterpreting your question, but do you mean something like this?
February 8th, 2007 at 6:46 pmalias old_try try
def try(hash, &block)
old_try(hash[:x], hash[:y], hash[:z], &block)
end
As Phrogz showed in the ML:
# unmodified
def try(x, y, z)
(yield * y) if block_given?
end
# ^^^^
alias old_try try
def try(hash, &block)
old_try(*hash.values_at(:a, :b, :c), &block)
end
try(:a => 1, :b => 5, :c => 3) { "foo" } # => "foofoofoofoofoo"
February 8th, 2007 at 7:05 pmRUBY_VERSION # => "1.8.5"
forgot to say that the &Proc.new thing also works, but &block is better and does what you want
February 8th, 2007 at 7:06 pmcould your “new” try method just be something like:
February 8th, 2007 at 7:13 pmdef try(hash,&block)
if block
old_try(hash[:x], hash[:y], hash[:z] ) { |self| block.call(self) }
else
old_try(hash[:x], hash[:y], hash[:z])
end
end
@Aaron (and mfp): I was looking for some way that doesn’t require me to modify the original source code for
try().@Brian: Good idea! I think that should do the trick.
February 8th, 2007 at 7:23 pm@Mauricio: OK, I now see that the method that you and Phrogz were recommending does work, at least with a little sample program I wrote. For some reason I didn’t think that it was working properly in my “real” code; I need to go back and see what I was doing differently.
@Brian: Joel VanderWerf (from the ML) suggested a similar approach, but just doing another “yield self” in the block instead of using
February 8th, 2007 at 7:37 pmblock.call(self). I think either one should work similarly.