From: Tanaka Akira Date: 2012-09-08T09:30:40+09:00 Subject: [ruby-core:47455] Re: [ruby-trunk - Bug #6994][Open] yield plus splat unwraps too much 2012/9/8 headius (Charles Nutter) : > Bug #6994: yield plus splat unwraps too much > https://bugs.ruby-lang.org/issues/6994 > system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; end; foo {|a, b, *c| p [a,b,c]}" > [[1], nil, []] This behavior causes "yield *[[1]]" and "yield [1]" is different: % ruby-1.8 -e "def foo; yield *[[1]]; end; foo {|a, b, *c| p [a,b,c]}" [[1], nil, []] % ruby-1.8 -e "def foo; yield [1]; end; foo {|a, b, *c| p [a,b,c]}" [1, nil, []] % ruby-1.8 -v ruby 1.8.8dev (2012-05-21 revision 26840) [x86_64-linux] So, information passed by yield to a block is not only a list of values but also something differentiate the above behaviors. It makes us impossible to pass block arguments as follows: def test() m() {|*vals| yield(*vals) } end This passes only a list of values from test() to m(). So the information for "something differentiate the above behaviors" is discarded. > system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo {|a, b, *c| p [a,b,c]}" > [1, nil, []] Since Ruby 1.9, information passed by yield to a block is only a list of values. So "yield *[[1]]" and "yield [1]" behaves same: % ruby -e "def foo; yield *[[1]]; end; foo {|a, b, *c| p [a,b,c]}" [1, nil, []] % ruby -e "def foo; yield [1]; end; foo {|a, b, *c| p [a,b,c]}" [1, nil, []] % ruby -v ruby 2.0.0dev (2012-08-15 trunk 36702) [x86_64-linux] Splat works in callee side. It expands single array. It cannot distinguish "yield *[[1]]" and "yield [1]". > JRuby behaves like 1.8 in both 1.8 and 1.9 modes. I would feel pretty dirty fixing it, since I think the 1.9.3/2.0.0 behavior is wrong. I don't think Ruby 1.9 behavior is wrong. -- Tanaka Akira