diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 61141bc606..7015f25c86 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -357,8 +357,9 @@ Notice that this really is an expression, as it evaluates to a result: ```scala import scala.annotation.switch -// `i` is an integer -val day = i match +val i = 5 // `i` is an integer + +val day = (i : @switch) match case 0 => "Sunday" case 1 => "Monday" case 2 => "Tuesday" @@ -367,6 +368,8 @@ val day = i match case 5 => "Friday" case 6 => "Saturday" case _ => "invalid day" // the default, catch-all + +println(day) ``` In this example the variable `i` is tested against the cases shown. @@ -382,10 +385,14 @@ Otherwise, the catch-all case is represented by the `_` character, and `day` is When you need to access the catch-all, default value in a `match` expression, just provide a variable name on the left side of the `case` statement, and then use that variable name on the right side of the statement as needed: ```scala -i match - case 0 => println("1") - case 1 => println("2") - case what => println(s"You gave me: $what" ) +val i = 4 + +val code = i match + case 0 => "00" + case 1 => "01" + case what => s"You gave me: $what" + +println(code) ``` In this example the variable is named `what` to show that it can be given any legal name. @@ -398,10 +405,14 @@ As mentioned, `match` expressions have many capabilities. This example shows how to use multiple possible pattern matches in each `case` statement: ```scala +val i = 6 + val evenOrOdd = i match - case 1 | 3 | 5 | 7 | 9 => println("odd") - case 2 | 4 | 6 | 8 | 10 => println("even") - case _ => println("some other number") + case 1 | 3 | 5 | 7 | 9 => "odd" + case 2 | 4 | 6 | 8 | 10 => "even" + case _ => "some other number" + +println(evenOrOdd) ``` @@ -411,21 +422,29 @@ You can also use guards in the `case`s of a match expression. In this example the second and third `case` both use guards to match multiple integer values: ```scala -i match - case 1 => println("one, a lonely number") - case x if x == 2 || x == 3 => println("two’s company, three’s a crowd") - case x if x > 3 => println("4+, that’s a party") - case _ => println("i’m guessing your number is zero or less") +val i = 3 + +val message = i match + case 1 => "one, a lonely number" + case x if x == 2 || x == 3 => "two’s company, three’s a crowd" + case x if x > 3 => "4+, that’s a party" + case _ => "i’m guessing your number is zero or less" + +println(message) ``` Here’s another example, which shows how to match a given value against ranges of numbers: ```scala -i match - case a if 0 to 9 contains a => println(s"0-9 range: $a") - case b if 10 to 19 contains b => println(s"10-19 range: $b") - case c if 20 to 29 contains c => println(s"20-29 range: $c") - case _ => println("Hmmm...") +val i = 12 + +val range = i match + case a if 0 to 9 contains a => s"0-9 range: $a" + case b if 10 to 19 contains b => s"10-19 range: $b" + case c if 20 to 29 contains c => s"20-29 range: $c" + case _ => "Hmmm..." + +println(range) ``` @@ -438,12 +457,12 @@ Here’s an example using a simple `Person` case class: case class Person(name: String) def speak(p: Person) = p match - case Person(name) if name == "Fred" => println(s"$name says, Yubba dubba doo") - case Person(name) if name == "Bam Bam" => println(s"$name says, Bam bam!") - case _ => println("Watch the Flintstones!") + case Person(name) if name == "Fred" => s"$name says, Yabba-Dabba-Doo!" + case Person(name) if name == "Bam Bam" => s"$name says, Bam bam!" + case _ => "Watch the Flintstones!" -speak(Person("Fred")) // "Fred says, Yubba dubba doo" -speak(Person("Bam Bam")) // "Bam Bam says, Bam bam!" +println(speak(Person("Fred"))) // "Fred says, Yabba-Dabba-Doo!" +println(speak(Person("Bam Bam"))) // "Bam Bam says, Bam bam!" ``` diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index 233c51b847..da050705ec 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -13,7 +13,7 @@ This section introduces the various aspects of how to define and call methods in Scala methods have many features, including these: -- Generic (type) parameters +- Generic methods with type parameters - Default parameter values - Multiple parameter groups - Context-provided parameters @@ -197,14 +197,13 @@ engage( -## A suggestion about methods that take no parameters +## A convention about methods that take no parameters -When a method takes no parameters, it’s said to have an _arity_ level of _arity-0_. -Similarly, when a method takes one parameter it’s an _arity-1_ method. +When a method takes no parameters, it’s said to have an _arity_ level of _arity-0_. Similarly, when a method takes one parameter it’s an _arity-1_ method. When you create arity-0 methods: - If the method performs side effects, such as calling `println`, declare the method with empty parentheses -- If the method does not perform side effects---such as getting the size of a collection, which is similar to accessing a field on the collection---leave the parentheses off +- If the method does not perform side effects---leave the parentheses off For example, this method performs a side effect, so it’s declared with empty parentheses: @@ -219,7 +218,8 @@ speak // error: "method speak must be called with () argument" speak() // prints "hi" ``` -While this is just a convention, following it dramatically improves code readability: It makes it easier to understand at a glance that an arity-0 method performs side effects. +This is known in Scala as the "uniform access principle". It states that variables and parameterless functions should be accessed using the same syntax. Scala supports this principle by not allowing parentheses to be placed at call sites of parameterless functions. + {% comment %} Some of that wording comes from this page: https://docs.scala-lang.org/style/method-invocation.html @@ -269,7 +269,7 @@ For more details on the `Matchable` trait, see the [Reference documentation][ref ## Controlling visibility in classes -In classes, objects, traits, and enums, Scala methods are public by default, so the `Dog` instance created here can access the `speak` method: +In classes, objects, traits, and enums, Scala methods are public by default, so world can access the `speak` method of `Dog` instance created here: ```scala class Dog: @@ -279,8 +279,7 @@ val d = new Dog d.speak() // prints "Woof" ``` -Methods can also be marked as `private`. -This makes them private to the current class, so they can’t be called nor overridden in subclasses: +Methods can also be marked as `private`. This makes them private to the current class, so they can’t be called or overridden in subclasses: ```scala class Animal: @@ -288,7 +287,7 @@ class Animal: class Cat extends Animal: // this method won’t compile - override def breathe() = println("Yo, I’m totally breathing") + override def breathe() = println("Meow. I’m breathing too.") ``` If you want to make a method private to the current class and also allow subclasses to call it or override it, mark the method as `protected`, as shown with the `speak` method in this example: @@ -299,10 +298,10 @@ class Animal: def walk() = breathe() println("I’m walking") - protected def speak() = println("Hello?") + protected def speak() = println("Hi people") class Cat extends Animal: - override def speak() = println("Meow") + override def speak() = println("Meow people") val cat = new Cat cat.walk() @@ -321,7 +320,7 @@ The `protected` setting means: Earlier you saw that traits and classes can have methods. The Scala `object` keyword is used to create a singleton class, and an object can also contain methods. -This is a nice way to group a set of “utility” methods. +This is a usual way to group a set of “utility” methods. For instance, this object contains a collection of methods that work on strings: ```scala @@ -383,23 +382,6 @@ See the [Extension methods section][reference_extension_methods] of this book, a -## Even more - -There’s even more to know about methods, including how to: - -- Call methods on superclasses -- Define and use by-name parameters -- Write a method that takes a function parameter -- Create inline methods -- Handle exceptions -- Use vararg input parameters -- Write methods that have multiple parameter groups (partially-applied functions) -- Create methods that have generic type parameters - -See the [Reference documentation][reference] for more details on these features. - - - [extension]: {% link _overviews/scala3-book/ca-extension-methods.md %} [reference_extension_methods]: {{ site.scala3ref }}/contextual/extension-methods.html [reference]: {{ site.scala3ref }}/overview.html diff --git a/_overviews/scala3-book/methods-summary.md b/_overviews/scala3-book/methods-summary.md index 9894c6d4c9..0a96ac2f9b 100644 --- a/_overviews/scala3-book/methods-summary.md +++ b/_overviews/scala3-book/methods-summary.md @@ -17,7 +17,7 @@ There’s even more to know about methods, including how to: - Handle exceptions - Use vararg input parameters - Write methods that have multiple parameter groups (partially-applied functions) -- Create methods that have generic type parameters +- Create methods that have type parameters See the [Reference documentation][reference] for more details on these features.