Skip to content

Nest patterns in guards #17727

@odersky

Description

@odersky

Motivation

I often come across a situation where I need to match on some outer pattern and then match on some attribute of the value exposed by that pattern. If the second match is not exhaustive it means I need the same fall back clause for the inner as well as the outer match, which is annoying. Consider for example the following class hierarchy:

sealed class T:
  def underlying: T = ...
class A extends T
class B extends T
class C extends T

I want to match on T's that have an underlying A or B and return a fallback for the rest. In current Scala, here's what I need to do:

x match
  case x: T =>
    x.underlying match
      case x: A => ...
      case x: B => ...
      case _ => fallback
  case _ => fallback

The duplication of fallback is annoying, in particular if fallback is naturally a list of cases by itself.

The proposal here is to introduce the following shorthand:

x match
  case x: T if x.underlying match
    case x: A => ...
    case x: B => ...
  case _ => fallback

Syntax:

CaseClause   ::=  `case` Pattern [Guard] `=>` Block
              |   `case` Pattern `if` InfixExpr MatchClause 
              |   `case` Pattern `if` [InfixExpr `&&`] SimpleExpr `.` MatchClause

Informal Specification:

A pattern guard may end in a match expression, which in this case replaces the pattern's right hand side.
If some clause of the second match expression matches, its right hand side defines the result of the match as a whole. If no clause in the second match expression matches, the next clause of the outer match is tried.

Related proposals

Both of these allow a single destructuring in a guard, whereas the proposal here allows multiple destructings. IMO either approach would be an improvement on what we have.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions