Ruby 1.9 introduced === on lambdas/procs so that you can put them in case statements. I'm a fan of this, but there's an unfortunate side effect I've run into recently.
If you have a lambda that accepts 0 args (e.g. lambda { }) or requires more than 1 arg (e.g. lambda { |x, y| }), calling === on it will raise an ArgumentError. I understand why: lambdas are strict about the number of arguments, and === is just an alias of call now. However, this makes things difficult in a gem when you want to use === to match arbitrary objects (since it's the general-purpose protocol ruby provides for that purpose) and there may be lambdas provided by the user. I ran into this in RSpec recently, and my (hacky) solution is to rescue ArgumentError:
It would be nice not to have to do this, and IMO, === on all built-in types should maintain the contract that they can be called with 1 arg and will not raise an error. Consider that ruby's syntax doesn't even allow you to call === with 0 or more than 1 argument unless you resort to hacks like send (e.g. obj.send(:===, x, y, z)). Given that, I think that === on lambdas should return false rather than raising an ArgumentError if the lambda does not support being called with 1 argument.
Users can use rspec's expectations with any kind of object. We can't arbitrarily restrict it and say, "you can't use lambdas". With some new features we're adding, we're leveraging ruby's === protocol, and we can't control what kind of objects users pass to us.
Why is it desirable for a built-in type to raise ArgumentError for === rather than returning false?
This seems odd behaviour, given that in normal usage you'd never be able to satisfy the constraint to avoid the ArgumentError, I feel this should return false like a proc would do.
Consider that ruby's syntax doesn't even allow you to call === with 0 or more than 1 argument unless you resort to hacks like send
The syntax allows it, you just need a dot:
-> a, b { a + b }.=== 1,2
-> a, b { a + b }.===(1,2)
-> { 42 }.===
-> { 42 }.===()
Interesting. You learn something new everyday :).
I'd still put this in the category of hacks like send, though: the normal, idiomatic way of calling operator methods in ruby is to not use a dot. When was the last time you used a dot to send a message like +, -, ==, ===, *, etc?