Project

General

Profile

Bug #11771

unable to pass keyargs to []=

Added by bughit (bug hit) almost 4 years ago. Updated almost 4 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:71836]

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

History

Updated by normalperson (Eric Wong) almost 4 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) almost 4 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.2

I'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) almost 4 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) almost 4 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) almost 4 years ago

I don't say anything about 3.0 for now.
But things are more complicated than you imagine.

Matz.

Also available in: Atom PDF