Feature #16355


Raise NoMatchingPatternError when `expr in pat` doesn't match

Added by ktsj (Kazuki Tsujimoto) about 3 years ago. Updated about 3 years ago.

Target version:


Currently, single line pattern matching(expr in pat) returns true or false.

[1, 2, 3] in [x, y, z] #=> true (with assigning 1 to x, 2 to y, and 3 to z)
[1, 2, 3] in [1, 2, 4] #=> false

I think expr in pat should raise an exception when it doesn't match.
Because if a user doesn't check the return value of expr in pat, matching failure occurs implicitly and it may cause problems in subsequent processes.

expr in [0, x] # A user expects it always matches, but if it doesn't match...
... #=> NoMethodError (undefined method `foo' for nil:NilClass)

I also propose that expr in pat returns the result of expr if it matches.
It is similar to assignment.

x, y, z = 1, 2, 3      #=> [1, 2, 3]
[1, 2, 3] in [x, y, z] #=> [1, 2, 3]


expr-in-pat-raises-error.patch (2.59 KB) expr-in-pat-raises-error.patch ktsj (Kazuki Tsujimoto), 11/20/2019 12:58 AM

Related issues 3 (1 open2 closed)

Related to Ruby master - Feature #15865: `<expr> in <pattern>` expressionClosedmatz (Yukihiro Matsumoto)Actions
Related to Ruby master - Feature #16370: Pattern matching with variable assignment (the priority of `in` operator)OpenActions
Related to Ruby master - Feature #17371: Reintroduce `expr in pat`ClosedActions
Actions #1

Updated by ktsj (Kazuki Tsujimoto) about 3 years ago

Actions #2

Updated by ktsj (Kazuki Tsujimoto) about 3 years ago

  • Description updated (diff)

Updated by palkan (Vladimir Dementyev) about 3 years ago

Agree, that it could save users from unexpected behavior.

On the other hand, raising an exception drastically limits the application of online pattern matching: it won't be possible to use it with if ... else ... or in select/filter statements (here is a great example).

If users won't to ensure that a pattern matches, they can write (expr in ptrn) || raise "smth".

Having one-line patterns return true or false brings a lot of possibilities, IMO.

P.S. I was actually scanning the tracker for the mentions of the following situation I've just encountered:

assert_block do
  {a:0, b: 1} in {a:, **nil}
  a.nil? #=> this is not nil, which confused me at first; but now I think that this is a less evil than raising an exception

Updated by Eregon (Benoit Daloze) about 3 years ago

I think this basically breaks [Feature #15865].

We should decide if expr in pattern can be used as a condition (such as in if) or not.

As @palkan (Vladimir Dementyev) said, it's already easy to use || raise NoMatchingPatternError for assignment cases, but it's impossible (or very ugly) to use if expr in pattern if we do the proposed change.

Updated by matz (Yukihiro Matsumoto) about 3 years ago

I accept this proposal for two reasons:

  • as OP described, returning boolean values from in pattern matching masks match failure. This can cause serious problems.
  • By this change, we cannot use in pattern matching in if conditionals. But this style can be easily expressed by case pattern matching.


Actions #6

Updated by nobu (Nobuyoshi Nakada) about 3 years ago

  • Status changed from Open to Closed

Applied in changeset git|8b4ee5d6ba92a385eedc9235ce0a2d5618deecf0.

Raise NoMatchingPatternError when expr in pat doesn't match

  • expr in pattern should raise NoMatchingError when unmatched
  • expr in pattern should return nil. (this is unspecified, but
    this feature is experimental, at all)

[Feature #16355]

Actions #7

Updated by ktsj (Kazuki Tsujimoto) about 3 years ago

  • Related to Feature #16370: Pattern matching with variable assignment (the priority of `in` operator) added
Actions #8

Updated by ktsj (Kazuki Tsujimoto) about 2 years ago


Also available in: Atom PDF