Forum: Ruby-core [ruby-trunk - Bug #6994][Open] yield plus splat unwraps too much

Posted by Charles Nutter (headius)
on 2012-09-07 21:09
(Received via mailing list)
Issue #6994 has been reported by headius (Charles Nutter).

----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Posted by Charles Nutter (headius)
on 2012-09-07 21:10
(Received via mailing list)
Issue #6994 has been updated by headius (Charles Nutter).


Related JRuby bug: http://jira.codehaus.org/browse/JRUBY-6499
----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994#change-29213

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Posted by Tanaka Akira (Guest)
on 2012-09-08 02:30
(Received via mailing list)
2012/9/8 headius (Charles Nutter) <headius@headius.com>:

> 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.
Posted by Charles Nutter (headius)
on 2012-09-08 17:26
(Received via mailing list)
Issue #6994 has been updated by headius (Charles Nutter).


What you're saying makes some sense if we treat all multiple-argument 
blocks as having an implicit () around them, since that makes method 
argument behavior match:

system ~ $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo {|a,b| p a}"
1

system ~ $ ruby-1.9.3 -e "def foo((a, b)); p a; end; foo *[[1]]"
1

But this isn't consistent either, since the single-argument form does 
not spread arrays:

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a| p a}"
[1]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo((a)); p a; end; foo 
*[[1]]"
1

So it spreads an incoming array out when there's more than one receiving 
argument, but does not spread it out when there's only one receiving 
argument?
----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994#change-29217

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Posted by Tanaka Akira (Guest)
on 2012-09-11 00:53
(Received via mailing list)
2012/9/9 headius (Charles Nutter) <headius@headius.com>:

> But this isn't consistent either, since the single-argument form does not spread 
arrays:
>
> system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo {|a| p 
a}"
> [1]
>
> system ~/projects/jruby $ ruby-1.9.3 -e "def foo((a)); p a; end; foo *[[1]]"
> 1
>
> So it spreads an incoming array out when there's more than one receiving 
argument, but does not spread it out when there's only one receiving argument?

Single array expansion is not always performed.
It depends on the form of the block arguments.

As you said, {|a| } doesn't expand.
If {|a| } expands an array, we cannot get an element of a nested array 
in
[ary, ary, ...].each {|a| ... }.

Also, {|*a| } doesn't expand.
If {|*a| } expands an array, we cannot pass block arguments as-is
using {|*a| yield *a }.

I wrote about this design in [ruby-dev:38795].  It is written in
Japanese, though.
Posted by Charles Nutter (headius)
on 2012-09-19 09:08
(Received via mailing list)
Issue #6994 has been updated by headius (Charles Nutter).


Ok, I accept the explanation. We will support the MRI behavior in JRuby.
----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994#change-29506

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Posted by Charles Nutter (headius)
on 2012-10-14 22:03
(Received via mailing list)
Issue #6994 has been updated by headius (Charles Nutter).


This can be closed.
----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994#change-30670

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Posted by kosaki (Motohiro KOSAKI) (Guest)
on 2012-10-15 04:19
(Received via mailing list)
Issue #6994 has been updated by kosaki (Motohiro KOSAKI).

Status changed from Open to Rejected


----------------------------------------
Bug #6994: yield plus splat unwraps too much
https://bugs.ruby-lang.org/issues/6994#change-30688

Author: headius (Charles Nutter)
Status: Rejected
Priority: Normal
Assignee:
Category:
Target version:
ruby -v: 2.0.0dev and 1.9.3p253


I don't see how anyone could argue that 1.9.3 and 2.0.0 are correct 
here:

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[1]; end; 
foo {|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[1]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.8.7-p358 -e "def foo; yield *[[[1]]]; 
end; foo {|a, b, *c| p [a,b,c]}"
[[[1]], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-1.9.3 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[1]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[1]]; end; foo 
{|a, b, *c| p [a,b,c]}"
[1, nil, []]

system ~/projects/jruby $ ruby-2.0.0 -e "def foo; yield *[[[1]]]; end; 
foo {|a, b, *c| p [a,b,c]}"
[[1], nil, []]

system ~/projects/jruby $ ruby-1.9.3 -v
ruby 1.9.3p253 (2012-07-04 revision 36307) [x86_64-darwin11.4.0]

system ~/projects/jruby $ ruby-2.0.0 -v
ruby 2.0.0dev (2012-08-27 trunk 36833) [x86_64-darwin11.4.0]

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.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.