Skip to content

Commit

Permalink
Merge pull request #3071 from gkepka/at-operator
Browse files Browse the repository at this point in the history
Examples for binding patterns to variables
  • Loading branch information
SethTisue authored Oct 26, 2024
2 parents 905ed27 + 8ec1d34 commit 69744f5
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
47 changes: 47 additions & 0 deletions _overviews/scala3-book/control-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,53 @@ speak(Person("Bam Bam")) // "Bam Bam says, Bam bam!"
{% endtab %}
{% endtabs %}

#### Binding matched patterns to variables

You can bind the matched pattern to a variable to use type-specific behavior.

{% tabs pattern-binding class=tabs-scala-version %}
{% tab 'Scala 2' for=pattern-binding %}
```scala
trait Animal {
val name: String
}
case class Cat(name: String) extends Animal {
def meow: String = "Meow"
}
case class Dog(name: String) extends Animal {
def bark: String = "Bark"
}

def speak(animal: Animal) = animal match {
case c @ Cat(name) if name == "Felix" => println(s"$name says, ${c.meow}!")
case d @ Dog(name) if name == "Rex" => println(s"$name says, ${d.bark}!")
case _ => println("I don't know you!")
}

speak(Cat("Felix")) // "Felix says, Meow!"
speak(Dog("Rex")) // "Rex says, Bark!"
```
{% endtab %}
{% tab 'Scala 3' for=pattern-binding %}
```scala
trait Animal:
val name: String
case class Cat(name: String) extends Animal:
def meow: String = "Meow"
case class Dog(name: String) extends Animal:
def bark: String = "Bark"

def speak(animal: Animal) = animal match
case c @ Cat(name) if name == "Felix" => println(s"$name says, ${c.meow}!")
case d @ Dog(name) if name == "Rex" => println(s"$name says, ${d.bark}!")
case _ => println("I don't know you!")

speak(Cat("Felix")) // "Felix says, Meow!"
speak(Dog("Rex")) // "Rex says, Bark!"
```
{% endtab %}
{% endtabs %}

### Using a `match` expression as the body of a method

Because `match` expressions return a value, they can be used as the body of a method.
Expand Down
21 changes: 21 additions & 0 deletions _tour/pattern-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,27 @@ def goIdle(device: Device): String = device match

`def goIdle` has a different behavior depending on the type of `Device`. This is useful when the case needs to call a method on the pattern. It is a convention to use the first letter of the type as the case identifier (`p` and `c` in this case).

## Binding matched patterns to variables
You can use variable binding to get type-dependent behavior while simultaneously extracting fields from the matched pattern.

{% tabs pattern-matching-variable-binding class=tabs-scala-version %}
{% tab 'Scala 2' for=pattern-matching-variable-binding %}
```scala mdoc
def goIdleWithModel(device: Device): String = device match {
case p @ Phone(model) => s"$model: ${p.screenOff}"
case c @ Computer(model) => s"$model: ${c.screenSaverOn}"
}
```
{% endtab %}
{% tab 'Scala 3' for=pattern-matching-variable-binding %}
```scala
def goIdleWithModel(device: Device): String = device match
case p @ Phone(model) => s"$model: ${p.screenOff}"
case c @ Computer(model) => s"$model: ${c.screenSaverOn}"
```
{% endtab %}
{% endtabs %}

## Sealed types

You may have noticed that in the examples above the base types are qualified
Expand Down

0 comments on commit 69744f5

Please sign in to comment.