Bug #5328
closedSplat args are treated wrongly in instance_exec and class_exec
Description
This gist demonstrates the issue:
https://gist.github.com/1218664
On 1.8.7, instance_exec and class_exec treat splat block args the same as method splat args. On 1.9, it is treated differently and this is very unexpected.
Updated by ko1 (Koichi Sasada) about 12 years ago
- Status changed from Open to Assigned
- Assignee set to akr (Akira Tanaka)
Updated by akr (Akira Tanaka) almost 10 years ago
- Status changed from Assigned to Rejected
Ruby 1.9 changes block arguments behavior.
Non-lambda block arguments always expands single array.
(Ruby 1.8 expands sometimes.)
If you needs block arguments behaving as methods, use lambda.
% cat splat_args
def foo(arg_1, *arg_2)
puts "Arguments received by method:"
puts "arg_1: #{arg_1.inspect}"
puts "arg_2: #{arg_2.inspect}"
end
foo([1, 2, 3])
puts
Class.class_exec([1, 2, 3]) do |arg_1, *arg_2|
puts "Arguments received by class_exec:"
puts "arg_1: #{arg_1.inspect}"
puts "arg_2: #{arg_2.inspect}"
end
puts
instance_exec([1, 2, 3]) do |arg_1, *arg_2|
puts "Arguments received by instance_exec:"
puts "arg_1: #{arg_1.inspect}"
puts "arg_2: #{arg_2.inspect}"
end
puts
Class.class_exec([1, 2, 3], &lambda do |arg_1, *arg_2|
puts "Arguments received by class_exec(lambda):"
puts "arg_1: #{arg_1.inspect}"
puts "arg_2: #{arg_2.inspect}"
end)
puts
instance_exec([1, 2, 3], &lambda do |arg_1, *arg_2|
puts "Arguments received by instance_exec(lambda):"
puts "arg_1: #{arg_1.inspect}"
puts "arg_2: #{arg_2.inspect}"
end)
% ruby-1.9.1p0 splat_args
Arguments received by method:
arg_1: [1, 2, 3]
arg_2: []
Arguments received by class_exec:
arg_1: 1
arg_2: [2, 3]
Arguments received by instance_exec:
arg_1: 1
arg_2: [2, 3]
Arguments received by class_exec(lambda):
arg_1: [1, 2, 3]
arg_2: []
Arguments received by instance_exec(lambda):
arg_1: [1, 2, 3]
arg_2: []
Updated by myronmarston (Myron Marston) almost 10 years ago
Thanks for taking the time to explain.
This surprises me a bit because I've followed ruby development closely for a number of years and this is the first time I've heard of this particular proc vs lambda difference (I know of others like the difference in return
and ArgumentError
if a lambda is given the wrong number of args). It also seems very counterintuitive to me.
Is there a prior issue where this was discussed? I'd like to read up on it.
Thanks!
Updated by akr (Akira Tanaka) almost 10 years ago
I can remember several documents.
- The document of Proc#lambda?.
- The thread from ruby-core:47453 "yield plus splat unwraps too much"
(I don't recommend reading it in bugs.ruby-lang.org because messages are unintentionally formatted as markdown.) - ruby-dev:38795 (in Japanese)
Note that "always expands single array" was mistake.
The expantion also depends on the form of block arguments.
Updated by myronmarston (Myron Marston) almost 10 years ago
Thanks. I'm still trying to wrap my head around it but that's quite helpful.