Project

General

Profile

Feature #16355

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

Added by ktsj (Kazuki Tsujimoto) 10 months ago. Updated 10 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:95889]

Description

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...
...
(snip)
...
x.foo #=> 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]

Files

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

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
#1

Updated by ktsj (Kazuki Tsujimoto) 10 months ago

#2

Updated by ktsj (Kazuki Tsujimoto) 10 months ago

  • Description updated (diff)

Updated by palkan (Vladimir Dementyev) 10 months 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
end

Updated by Eregon (Benoit Daloze) 10 months 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) 10 months 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.

Matz.

#6

Updated by nobu (Nobuyoshi Nakada) 10 months 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]

#7

Updated by ktsj (Kazuki Tsujimoto) 10 months ago

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

Also available in: Atom PDF