Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forwarding multiple arguments to method reference fails #1629

Closed
okirmis opened this issue Mar 20, 2019 · 4 comments
Closed

Forwarding multiple arguments to method reference fails #1629

okirmis opened this issue Mar 20, 2019 · 4 comments
Assignees
Milestone

Comments

@okirmis
Copy link

okirmis commented Mar 20, 2019

Forwarding multiple arguments to a method reference works in MRI, but fails in truffleruby. Example:

def two_argument_method(key, value)
  puts "#{key}: #{value}"
end

hash = { a: 1 }
hash.each(&method(:two_argument_method))

On MRI it prints a: 1 to the command line. Truffleruby fails with:

minimal_example.rb:1:in `two_argument_method': wrong number of arguments (given 1, expected 2) (ArgumentError)
        from minimal_example.rb:1:in `two_argument_method'
        from minimal_example.rb:6:in `each'
        from minimal_example.rb:6:in `<main>'

Hash#each passes two arguments. Forwarding single arguments, e.g. with Array#each works fine.

> ruby --version
truffleruby 1.0.0-rc10, like ruby 2.4.4, GraalVM CE Native [x86_64-linux]

Edit: For some reason it pretends to be rc10, but I used rvm install truffleruby-1.0.0-rc14 and rvm use.... RVM said Found remote file https://github.com/oracle/truffleruby/releases/download/vm-1.0.0-rc14/truffleruby-1.0.0-rc14-linux-amd64.tar.gz so I believe it's actually rc14.

@eregon
Copy link
Member

eregon commented Mar 20, 2019

I would trust the ruby --version output, this is probably a RVM bug, see rvm/rvm#4633

Anyway, the given example still fails on master, so the version doesn't matter for this bug report.

@eregon
Copy link
Member

eregon commented Mar 20, 2019

This seems to be a bug of Hash#each rather, which currently yields an Array of 2 elements instead of yielding 2 arguments:

def two_argument_method(key, value)
  puts "#{key}: #{value}"
end

def y
  yield 1, 2
end

y(&-> a,b { p [a,b] })
y(&method(:two_argument_method))

hash = { a: 1 }
hash.each(&-> a,b { p [a,b] })
hash.each(&method(:two_argument_method))

On TruffleRuby master:

[1, 2]
1: 2
methargs.rb:14:in `block in <main>': wrong number of arguments (given 1, expected 2) (ArgumentError)
	from methargs.rb:14:in `each'
	from methargs.rb:14:in `<main>'

@eregon
Copy link
Member

eregon commented Mar 21, 2019

@okirmis Fix for this coming.

I wouldn't recommend using Method or lambdas with yielding methods from Array/Hash in general, because it's quite inconsistent what works and what doesn't. Better to use a block and delegate explicitly, that always works no matter the core method used.
In this case, there is no way to pass all specs with a single choice between yielding 2 arguments or an Array of 2 elements, so MRI actually introduced a special case just to make this work (maybe for compatibility?):
https://github.com/ruby/ruby/blob/638c96858274deb90b2b923477d6b9525e1ed065/hash.c#L2870-L2878

@eregon
Copy link
Member

eregon commented Mar 22, 2019

@okirmis Thank you for the report. I fixed this in 7c7997b and it will be in the next release, 1.0.0-rc15.

@eregon eregon closed this as completed Mar 22, 2019
@eregon eregon added this to the 1.0.0-rc15 milestone Mar 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants