From 07a0c4674e72ad76202929062949e7ba7f62eb03 Mon Sep 17 00:00:00 2001 From: gkepka Date: Sun, 8 Sep 2024 13:00:11 +0200 Subject: [PATCH 1/2] Examples for binding patterns to variables --- _overviews/scala3-book/control-structures.md | 47 ++++++++++++++++++++ _tour/pattern-matching.md | 37 +++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 6598cb604..b982cf654 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -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. diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index 1038e6be1..bca07f089 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -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 From 8ec1d34527adb813140a26254b47510ffddcf3aa Mon Sep 17 00:00:00 2001 From: gkepka Date: Sun, 15 Sep 2024 21:20:41 +0200 Subject: [PATCH 2/2] Fix double declaration of classes and functions --- _tour/pattern-matching.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/_tour/pattern-matching.md b/_tour/pattern-matching.md index bca07f089..a89c16775 100644 --- a/_tour/pattern-matching.md +++ b/_tour/pattern-matching.md @@ -242,15 +242,7 @@ You can use variable binding to get type-dependent behavior while simultaneously {% 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 { +def goIdleWithModel(device: Device): String = device match { case p @ Phone(model) => s"$model: ${p.screenOff}" case c @ Computer(model) => s"$model: ${c.screenSaverOn}" } @@ -258,15 +250,7 @@ def goIdle(device: Device): String = device match { {% 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 +def goIdleWithModel(device: Device): String = device match case p @ Phone(model) => s"$model: ${p.screenOff}" case c @ Computer(model) => s"$model: ${c.screenSaverOn}" ```