Project

General

Profile

Bug #10142

named params don't always capture passed named args

Added by rits (First Last) over 5 years ago. Updated about 5 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]
[ruby-core:64402]

Description

irb(main):007:0> def foo(a, b: nil); [a, b] end
:foo
irb(main):008:0> foo b: 1
[
  [0] {
    :b => 1
  },
  [1] nil
]

would be better if this raised


Related issues

Related to Ruby master - Bug #10309: Unexpected keyword parameters becomes an additional mandatory parameterRejected10/01/2014Actions

History

Updated by nobu (Nobuyoshi Nakada) over 5 years ago

  • Description updated (diff)
  • Status changed from Open to Rejected

Mandatory arguments have priority over keywords arguments.

Updated by rits (First Last) over 5 years ago

Nobuyoshi Nakada wrote:

Mandatory arguments have priority over keywords arguments.

instead of just restating what is, why don't you say why it should be this way.

before keyword args existed as first class citizens, it made sense for the keyword hash to be captured by the first free mandatory param, however now that they are first class, it makes no sense for the keyword arg x not to map to the first class keyword param x.

so before keyword args are turned into a hash and consumed by a mandatory param, actual keyword params shoud get a chance to consume them, few more examples:

irb(main):014:0> def foo(a, b:); [a, b] end
=> :foo
irb(main):015:0> foo c: 1, b: 1
ArgumentError: missing keyword: b

irb(main):019:0> def foo(a, b: 0); [a, b] end
=> :foo
irb(main):020:0> foo c: 1, b: 1
=> [{:c=>1, :b=>1}, 0]

in all three cases keyarg b: should map to keyparam b:

why is that not preferable?

Updated by rits (First Last) over 5 years ago

First Last wrote:

Nobuyoshi Nakada wrote:

Mandatory arguments have priority over keywords arguments.

instead of just restating what is, why don't you say why it should be this way.

before keyword args existed as first class citizens, it made sense for the keyword hash to be captured by the first free mandatory param, however now that they are first class, it makes no sense for the keyword arg x not to map to the first class keyword param x.

so before keyword args are turned into a hash and consumed a mandatory param, actual keyword params shoud get a chance to consume them, few more examples:

irb(main):014:0> def foo(a, b:); [a, b] end
=> :foo
irb(main):015:0> foo c: 1, b: 1
ArgumentError: missing keyword: b

this example is particularly illustrative, it's absurd to complain about missing keyword b when the method is being passed keyword b

Updated by ko1 (Koichi Sasada) over 5 years ago

(2014/08/16 12:49), meanlogin@gmail.com wrote:

this example is particularly illustrative, it's absurd to complain about missing keyword b when the method is being passed keyword b

What kind of message do you expect?

--
// SASADA Koichi at atdot dot net

Updated by rits (First Last) over 5 years ago

Koichi Sasada wrote:

(2014/08/16 12:49), meanlogin@gmail.com wrote:

this example is particularly illustrative, it's absurd to complain about missing keyword b when the method is being passed keyword b

What kind of message do you expect?

I already stated what I think would make more sense:

before keyword args are packaged into a hash which is bound to a mandatory param, actual first class keyword params should get a chance to bind to/consume them

in this specific example, key arg b would be bound to key param b, and the remaining key arg c would be put into a hash which would be bound to mandatory param a

I should underscore that I first discovered this issue in a real scenario, I forgot to pass one of several mandatory args to a method (first example) and instead of raising a helpful arg error it unbound an optional key arg x from key param x and bound it to the mandatory param.

Current behavior is surprising, illogical and promotes subtle bugs.

Updated by ko1 (Koichi Sasada) over 5 years ago

(2014/08/17 12:57), meanlogin@gmail.com wrote:

I already stated what I think would make more sense:

I understand that you are surprising.
I agree about this surprize.

But I can't find any concrete proposal.

--
// SASADA Koichi at atdot dot net

Updated by ko1 (Koichi Sasada) over 5 years ago

Sorry I missed this line.

in this specific example, key arg b would be bound to key param b, and the remaining key arg c would be put into a hash which would be bound to mandatory param a

Your proposal is to check keyword arguments before mandatory arguments.

Updated by rits (First Last) over 5 years ago

Koichi Sasada wrote:

Sorry I missed this line.

in this specific example, key arg b would be bound to key param b, and the remaining key arg c would be put into a hash which would be bound to mandatory param a

Your proposal is to check keyword arguments before mandatory arguments.

having never studied the actual implementation, this is as concrete as I can make it

"before keyword args are packaged into a hash which is bound to a mandatory param, actual first class keyword params should get a chance to bind to/consume them"

now that key args are first class, only those key args that failed to to bind to key params should be candidates for the fallback of hash packaging and binding to a regular param

Updated by rits (First Last) over 5 years ago

First Last wrote:

Koichi Sasada wrote:

Sorry I missed this line.

in this specific example, key arg b would be bound to key param b, and the remaining key arg c would be put into a hash which would be bound to mandatory param a

Your proposal is to check keyword arguments before mandatory arguments.

having never studied the actual implementation, this is as concrete as I can make it

"before keyword args are packaged into a hash which is bound to a mandatory param, actual first class keyword params should get a chance to bind to/consume them"

now that key args are first class, only those key args that failed to to bind to key params should be candidates for the fallback of hash packaging and binding to a regular param

Can you at least explain why this would not be better?

Updated by rits (First Last) about 5 years ago

another example of how this creates surprise, confusion and subtle bugs

def foo(a = 1, **options)
end

foo opt: 2

if 'a' becomes mandatory, instead of raising, "a" will absorb the options, which is clearly something no one would ever expect or want, when you have "**" specifically designed for this purpose

so why is the current behavior preferable?

Updated by ko1 (Koichi Sasada) about 5 years ago

  • Related to Bug #10309: Unexpected keyword parameters becomes an additional mandatory parameter added

Also available in: Atom PDF