Skip to content

Commit

Permalink
Fix #20271: Bring for comprehension spec up to date.
Browse files Browse the repository at this point in the history
Since Scala 3.4, a `withFilter` is generated if and only if the
generator has the `case` modifier.

If it does not, the pattern must be irrefutable.
  • Loading branch information
sjrd committed Oct 4, 2024
1 parent a672e05 commit 6f610cf
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions docs/_spec/06-expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -729,16 +729,17 @@ A _for loop_ `for (´\mathit{enums}\,´) ´e´` executes expression ´e´ for ea
A _for comprehension_ `for (´\mathit{enums}\,´) yield ´e´` evaluates expression ´e´ for each binding generated by the enumerators ´\mathit{enums}´ and collects the results.
An enumerator sequence always starts with a generator; this can be followed by further generators, value definitions, or guards.

A _generator_ `´p´ <- ´e´` produces bindings from an expression ´e´ which is matched in some way against pattern ´p´.
Optionally, `case` can appear in front of a generator pattern, this has no meaning in Scala 2 but will be [required in Scala 3 if `p` is not irrefutable](https://docs.scala-lang.org/scala3/reference/changed-features/pattern-bindings.html).
A _generator_ `´p´ <- ´e´` produces bindings from an expression ´e´ which is deconstructed by the pattern ´p´.
The pattern must be [irrefutable](08-pattern-matching.html#irrefutable-patterns).
A _conditional generator_ `case ´p´ <- ´e´` tests whether elements produces by ´e´ match the pattern and discards the ones that do not match.

A _value definition_ `´p´ = ´e´` binds the value name ´p´ (or several names in a pattern ´p´) to the result of evaluating the expression ´e´.
A _guard_ `if ´e´` contains a boolean expression which restricts enumerated bindings.
The precise meaning of generators and guards is defined by translation to invocations of four methods: `map`, `withFilter`, `flatMap`, and `foreach`.
These methods can be implemented in different ways for different carrier types.

The translation scheme is as follows.
In a first step, every generator `´p´ <- ´e´`, where ´p´ is not [irrefutable](08-pattern-matching.html#patterns) for the type of ´e´ is replaced by
In a first step, every generator `case ´p´ <- ´e´` is replaced by

```scala
´p´ <- ´e´.withFilter { case ´p´ => true; case _ => false }
Expand Down Expand Up @@ -772,7 +773,7 @@ Then, the following rules are applied repeatedly until all comprehensions have b
´e´.foreach { case ´p´ => for (´p'´ <- ´e'; ...´) ´e''´ }
```

- A generator `´p´ <- ´e´` followed by a guard `if ´g´` is translated to a single generator `´p´ <- ´e´.withFilter((´x_1, ..., x_n´) => ´g\,´)` where ´x_1, ..., x_n´ are the free variables of ´p´.
- A generator `´p´ <- ´e´` followed by a guard `if ´g´` is translated to a single generator `´p´ <- ´e´.withFilter({ case ´p´ => ´g\,´ })`.

- A generator `´p´ <- ´e´` followed by a value definition `´p'´ = ´e'´` is translated to the following generator of pairs of values, where ´x´ and ´x'´ are fresh names:

Expand Down

0 comments on commit 6f610cf

Please sign in to comment.