Project

General

Profile

Actions

Bug #8457

closed

Function arguments: Is this intended?

Added by Anonymous over 11 years ago. Updated over 11 years ago.

Status:
Closed
Target version:
-
ruby -v:
2.0.0
[ruby-core:55185]

Description

a = [1, 2, x: 3]
a.tap { |*p, q| a.clear.concat p } #=> [1, 2]

but

a = [1, 2, x: 3]
a.tap { |*p, **q| a.clear.concat p } #=> [[...]]

and also

a = [1, 2]
a.tap { |*p| a.clear.concat p } #=> [[...]]

???


Related issues 1 (0 open1 closed)

Related to Backport200 - Backport #8463: Proc auto-splat bug with named argumentsClosednagachika (Tomoyuki Chikanaga)05/30/2013Actions

Updated by matz (Yukihiro Matsumoto) over 11 years ago

  • Status changed from Open to Closed

I am not sure what you meant, but I am sure you are fooled by side-effect of #concat method.

a = [1, 2]
a.tap {|*p| # p is an array that wraps a i.e. p=[a]
a.clear # a is cleared; now p=[[]]
a.concat p # you concat p, that contains reference to a to a, make it circular
} # => a = [a]

This is not a bug.

Updated by phluid61 (Matthew Kerwin) over 11 years ago

=begin
boris_stitnicky (Boris Stitnicky) wrote:

a = [1, 2, x: 3]
a.tap { |*p, q| a.clear.concat p } #=> [1, 2]

but

a = [1, 2, x: 3]
a.tap { |*p, **q| a.clear.concat p } #=> [[...]]

and also

a = [1, 2]
a.tap { |*p| a.clear.concat p } #=> [[...]]

???

Is this the problem?

a = [1,2,x:3]
a.tap { |*p,**q| puts "p=#{p.inspect}, q=#{q.inspect}" }

prints: p=[[1, 2, {:x=>3}]], q={}

expected: p=[1, 2], q={:x=>3}

as per:

a = [1,2,x:3]
def foo(*p,**q) puts "p=#{p.inspect}, q=#{q.inspect}"; end
foo *a

prints: p=[1, 2], q={:x=>3}

?

Note that the same behaviour occurs if the block has a (({**})) parameter.
(Tried on ruby 2.1.0dev (2013-04-24 trunk 40439) [x86_64-linux] )
=end

Updated by marcandre (Marc-Andre Lafortune) over 11 years ago

  • Category set to core
  • Status changed from Closed to Open
  • Assignee set to matz (Yukihiro Matsumoto)

I'm wondering too if there isn't something strange?

I'd expect a proc to either do an implicit splat or not, but right now it looks for options before doing the implicit splat. Should it not do it after doing the implicit splat?

I thought that when a proc had an argument list with more than one element, it was the same to call it with a single array argument than with the same array splatted:

Proc{|a, ...| ... }.call([...]) == Proc{|a, ...}| ... }.call(*[...]) # => Because of implicit splat

But we have currently:

Proc.new{|a, *b, **c| p a, b, c}.call(1,2, bar: 3)

=> 1, [2], {:bar=>3} : OK

Proc.new{|a, *b, **c| p a, b, c}.call([1,2, bar: 3])

=> 1, [2, {:bar=>3}], {}: Expected same as above

Proc.new{|(a, *b), **c| p a, b, c}.call([1,2], bar: 3)

=> 1, [2], {:bar=>3} : OK

Proc.new{|(a, *b), **c| p a, b, c}.call([[1,2], bar: 3])

=> [1, 2], [{:bar=>3}], {}: Expected same as above

So, Matz, what do you think of these simplified examples?

Updated by marcandre (Marc-Andre Lafortune) over 11 years ago

As an additional note, this affects some methods of Enumerable when yielding multiple arguments.

For example:

def each; yield 1, 2, bar: 3; end
include Enumerable

each{|a, *b, **c| p a, b, c} # => 1, [2], {:bar => 3}: ok
detect{|a, *b, **c| p a, b, c} # => 1, [2, {:bar => 3}], {}: should be the same, no?

Updated by matz (Yukihiro Matsumoto) over 11 years ago

  • Status changed from Open to Closed

I admit there's a bug which Matthew mentioned, but it's not described in the OP.
Do you mind if I close this, and ask you to resubmit as a new bug report for the record.

Matz.

Updated by marcandre (Marc-Andre Lafortune) over 11 years ago

Thanks.
I created #8463

matz (Yukihiro Matsumoto) wrote:

I admit there's a bug which Matthew mentioned, but it's not described in the OP.
Do you mind if I close this, and ask you to resubmit as a new bug report for the record.

Matz.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0