From: dblack@... Date: 2006-01-05T03:57:08+09:00 Subject: Re: blk.call vs. yield (possible bug?) Hi -- On Tue, 3 Jan 2006, Dominik Bathon wrote: > Hello, > > I always thought that the following 4 methods should be equivalent if they > are called with one argument: > > def t1(*a) > yield *a > end > > def t2(*a, &blk) > blk.call(*a) > end > > def t3(a) > yield a > end > > def t4(a, &blk) > blk.call(a) > end > > > Well they don't seem to be: > > [:t1, :t2, :t3, :t4].each { |meth| > puts "================================" > p send(meth, [1, 2]) { |a,| a } > p send(meth, [1, 2]) { |a,b| [a, b] } > p send(meth, [1, 2]) { |a| a } > } > $ ruby -v > ruby 1.8.3 (2005-09-21) [i686-linux] > $ ruby tst.rb > ================================ > [1, 2] > [[1, 2], nil] > [1, 2] > ================================ > 1 > [1, 2] > [1, 2] > ================================ > 1 > [1, 2] > [1, 2] > ================================ > 1 > [1, 2] > [1, 2] I think it has something to do with the Proc/lambda difference. When you grab the block into a variable, it becomes a Proc object. Otherwise it behaves like a lambda: irb(main):001:0> pr = Proc.new {|a,| a } => # irb(main):002:0> la = lambda {|a,| a } => # irb(main):003:0> pr.call([1,2]) => 1 irb(main):004:0> la.call([1,2]) => [1, 2] I haven't tried all of them, but I strongly suspect you'll find that all the behavior you're finding goes back to this. I find it very hard to remember that there is a difference, to understand *why* there's a difference, and to remember what the difference is. I have to test them each time -- which may mean that I'm stupid, or it may mean that they're hard to understand and remember, or something in between. I'm still hoping for some kind of simplification or unification. (Maybe the YARV behavior is a sign of things to come?) David -- David A. Black dblack@wobblini.net "Ruby for Rails", from Manning Publications, coming April 2006! http://www.manning.com/books/black