Bug #10142
closednamed params don't always capture passed named args
Added by rits (First Last) over 10 years ago. Updated about 10 years ago.
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
Updated by nobu (Nobuyoshi Nakada) over 10 years ago
- Description updated (diff)
- Status changed from Open to Rejected
Mandatory arguments have priority over keywords arguments.
Updated by rits (First Last) over 10 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 10 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 10 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 10 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 10 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 10 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 10 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 10 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 10 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 10 years ago
- Related to Bug #10309: Unexpected keyword parameters becomes an additional mandatory parameter added