Bug #11771
closedunable to pass keyargs to []=
Description
module Foo
def self.[]=(key, val, option: nil)
end
end
Foo[:key] = 1 # ok
Foo[:key, option: 1] = 1 # wrong number of arguments (3 for 2)
if you declare the []= params using *
module Bar
def self.[]=(*args)
p args
end
end
Bar[:key, option: 1] = 1 # args: [:key, {:option=>1}, 1]
the args end up [:key, {:option=>1}, 1] which seems wrong since the keyargs hash is supposed to be last
Updated by normalperson (Eric Wong) over 8 years ago
Affects back to 2.0 (when keyword args were introduced),
so this doesn't seem to be an optimization bug introduced in 2.1/2.2
I'm actually not sure about the specs and if there's some special case
for kwargs interacting with aref/aset...
For instance, frequently use the 'sequel' API to write stuff like:
DB[:tbl][id: 123]
(I've been doing this since before keyword args were introduced)
Updated by bughit (bug hit) over 8 years ago
Eric Wong wrote:
Affects back to 2.0 (when keyword args were introduced),
so this doesn't seem to be an optimization bug introduced in 2.1/2.2I'm actually not sure about the specs and if there's some special case
for kwargs interacting with aref/aset...
The problem here is that the []= syntax compiled into a method dispatch where positional value arg is passed last, after keyargs, something you can't even do in ruby.
you can simulate the bug with a plain method:
def foo(key, val, option: nil)
end
foo(:key, 1, option: 1) # ok
foo(:key, {option: 1}, 1) # wrong number of arguments (3 for 2)
Updated by matz (Yukihiro Matsumoto) over 8 years ago
- Status changed from Open to Closed
Pending, for several reasons:
(1) compatibility. a[a,foo:1]=v
is valid code. changing behavior may crash existing code.
(2) you can delegate to other method e.g.
def opt_aset(k,v,option:nil)
...
end
def []=(k,opt={},v)
opt_aset(k,v,*opt)
end
Matz.
Updated by bughit (bug hit) over 8 years ago
Yukihiro Matsumoto wrote:
Pending, for several reasons:
(1) compatibility.
a[a,foo:1]=v
is valid code. changing behavior may crash existing code.
(2) you can delegate to other method e.g.def opt_aset(k,v,option:nil) ... end def []=(k,opt={},v) opt_aset(k,v,*opt) end
Matz.
def []=(k,opt={},v)
feels wrong because you're taking a dependency on incorrect behavior (method dispatch that puts a positional arg after the keyargs) Why not correct it for 3.0?
Updated by matz (Yukihiro Matsumoto) over 8 years ago
I don't say anything about 3.0 for now.
But things are more complicated than you imagine.
Matz.