Bug #11048
closed
blocks raise on missing and extra keyword args
Added by bughit (bug hit) over 9 years ago.
Updated over 9 years ago.
ruby -v:
ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
[ruby-core:<unknown>]
Description
blocks intentionally tolerate arity mismatches
irb(main):001:0> proc{|a, b| [a, b]}.(1)
[
[0] 1,
[1] nil
]
irb(main):003:0> proc{|a, b|[a, b]}.(1, 2, 3)
[
[0] 1,
[1] 2
]
so why not missing keyword args?
irb(main):002:0> proc{|a:, b:|[a, b]}.(a: 1)
ArgumentError: missing keyword: b
irb(main):004:0> proc{|a:, b:|[a, b]}.(a: 1, b: 1, c: 1)
ArgumentError: unknown keyword: c
- Assignee set to matz (Yukihiro Matsumoto)
We don't care about consistency here. Block does not report ArgumentError for reasons, so if you have any real-world use case that require keyword argument tolerance, just tell me. Otherwise I reject.
Matz.
Yukihiro Matsumoto wrote:
We don't care about consistency here. Block does not report ArgumentError for reasons,
What are those reasons? And why do they not apply to keyword arguments?
so if you have any real-world use case that require keyword argument tolerance, just tell me.
The real-world use case is that anyone who has learned that blocks intentionally tolerate arity mismatches, would expect the same for keyword args and will therefore be unpleasantly surprised and be more likely to introduce a bug.
And that's the value of consistency (or least surprise), behavior that is logically consistent, that can be inferred without having to remember countless of arbitrary special case rules, avoids surprise and bugs.
Since you value programmer joy, there is little joy in having to keep track of incoherent, inconsistent special case rules.
Yukihiro Matsumoto wrote:
so if you have any real-world use case that require keyword argument tolerance, just tell me.
The way I discovered this, as far as I remember, is:
I encountered a method I needed to call that yielded keyword args
In my case I only cared about one arg so I passed a block taking one keyarg, expecting it to just quietly drop the others as with positional args
Instead it raised
For example, loop
method passes loop counter to the block. You can safely ignore this by arity tolerance. This is a reason behind it. But there's no benefit for keyword arguments tolerance, as far as I see, but demerit of late error detection.
Matz.
Yukihiro Matsumoto wrote:
For example, loop
method passes loop counter to the block. You can safely ignore this by arity tolerance. This is a reason behind it. But there's no benefit for keyword arguments tolerance, as far as I see, but demerit of late error detection.
Matz.
If you believe there's value in being able to ignore args you don't care about, I don't see why it would not apply to keyargs. The difference is not so fundamental, both are used to pass data to the block. One might switch to keyargs for yield, to make the code clearer, but there would be no expectation of this difference in behavior.
- Status changed from Open to Closed
OK, you value consistency, where I value pragratic trade-off. That's the difference in view points.
Let's agree to disagree.
Matz.
- Status changed from Closed to Rejected
another use case for this is hash destructuring
array_of_hashes.each do |key1:, key2:|
end
it would be much better if this code did not raise on extra or missing keys, otherwise this type of destructuring is almost completely impractical
bug hit wrote:
another use case for this is hash destructuring
array_of_hashes.each do |key1:, key2:|
end
it would be much better if this code did not raise on extra or missing keys, otherwise this type of destructuring is almost completely impractical
Please comment on the use case of hash destructuring via block keyword args.
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0