Skip to content

Even more section literally doubles chapters Summary #2345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
67 changes: 43 additions & 24 deletions _overviews/scala3-book/control-structures.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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.
Expand All @@ -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)
```


Expand All @@ -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)
```


Expand All @@ -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, Yubba dubba 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, Yubba dubba doo"
println(speak(Person("Bam Bam"))) // "Bam Bam says, Bam bam!"
```


Expand Down
51 changes: 21 additions & 30 deletions _overviews/scala3-book/methods-most.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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---about such methods they say "pure methods" or "pure code", contrary to "dirty" or "impure"---leave the parentheses off

For example, this method performs a side effect, so it’s declared with empty parentheses:

Expand All @@ -219,7 +218,17 @@ 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.
The main intention behind this convention is to make transition field-to-method and visa-versa easy for developers and transparent to method consumers. For example, given the following code, no one can tell if `speak` is a field or method:

```scala
val alleyCat = Cat("Oliver")
println(alleyCat.speak)
```

In FP terms "call of pure function" and "result of pure function" (with given arguments) are totally the same thing. While code does not change any existing state we can substitute field instead of method, and method instead of the field. The result must be the same.

However, in the case of impure code consumers must be warned and alarmed at least, because impure code tends to make dangerous things, like throwing `IOException`. That is why there is a difference between an absent list and an empty argument list.


{% comment %}
Some of that wording comes from this page: https://docs.scala-lang.org/style/method-invocation.html
Expand Down Expand Up @@ -269,7 +278,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:
Expand All @@ -279,16 +288,15 @@ 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 nor overridden in subclasses:

```scala
class Animal:
private def breathe() = println("I’m breathing")

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:
Expand All @@ -299,10 +307,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()
Expand All @@ -321,7 +329,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
Expand Down Expand Up @@ -383,23 +391,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
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-book/methods-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down