Skip to content

Commit

Permalink
Examples for binding patterns to variables
Browse files Browse the repository at this point in the history
  • Loading branch information
gkepka committed Sep 8, 2024
1 parent 178372b commit 07a0c46
Show file tree
Hide file tree
Showing 2 changed files with 84 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
37 changes: 37 additions & 0 deletions _tour/pattern-matching.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,43 @@ 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
sealed trait Device
case class Phone(model: String) extends Device {
def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
def screenSaverOn = "Turning screen saver on..."
}

def goIdle(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
sealed trait Device
case class Phone(model: String) extends Device:
def screenOff = "Turning screen off"

case class Computer(model: String) extends Device:
def screenSaverOn = "Turning screen saver on..."


def goIdle(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 07a0c46

Please sign in to comment.