Bug #11048
closedblocks raise on missing and extra keyword args
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
Updated by ko1 (Koichi Sasada) over 9 years ago
- Assignee set to matz (Yukihiro Matsumoto)
Updated by matz (Yukihiro Matsumoto) over 9 years ago
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.
Updated by bughit (bug hit) over 9 years ago
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.
Updated by bughit (bug hit) over 9 years ago
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
Updated by matz (Yukihiro Matsumoto) over 9 years ago
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.
Updated by bughit (bug hit) over 9 years ago
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.
Updated by matz (Yukihiro Matsumoto) over 9 years ago
- 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.
Updated by usa (Usaku NAKAMURA) over 9 years ago
- Status changed from Closed to Rejected
Updated by bughit (bug hit) over 9 years ago
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
Updated by bughit (bug hit) over 9 years ago
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.