From: Myron@..., Marston@... Date: 2014-01-12T07:27:32+00:00 Subject: [ruby-core:59707] [ruby-trunk - Bug #9397] Lambda#=== raises `ArgumentError` if the lambda accepts 0 args or requires more than 1 Issue #9397 has been updated by Myron Marston. > Why lambda? > You can use proc for such purpose. 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? ---------------------------------------- Bug #9397: Lambda#=== raises `ArgumentError` if the lambda accepts 0 args or requires more than 1 https://bugs.ruby-lang.org/issues/9397#change-44224 * Author: Myron Marston * Status: Rejected * Priority: Normal * Assignee: * Category: * Target version: * ruby -v: 1.9+ * Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN, 2.1: UNKNOWN ---------------------------------------- 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`: https://github.com/rspec/rspec-support/commit/caf76c5de26ea1ca93f09f1097a0092ee4bf828d 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. -- http://bugs.ruby-lang.org/