From abc5ec13e81c1bc5445322c861bae6c3db00ff0f Mon Sep 17 00:00:00 2001 From: Arsenii Chebotarov Date: Wed, 9 Feb 2022 02:20:08 +0200 Subject: [PATCH 1/5] some better fp-wise reformating of 6 examples --- _overviews/scala3-book/control-structures.md | 67 +++++++++++++------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 61141bc606..4b141db65c 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 num = i match + case 0 => "00" + case 1 => "01" + case what => s"You gave me: $what" + +println(num) ``` 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, 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!" ``` From f0126ac1b9d8ca55cfc00f4d8de88857348bf306 Mon Sep 17 00:00:00 2001 From: Arsenii Chebotarov Date: Mon, 14 Mar 2022 21:59:50 +0200 Subject: [PATCH 2/5] fixed num => code --- _overviews/scala3-book/control-structures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 4b141db65c..186cc34e4d 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -387,12 +387,12 @@ When you need to access the catch-all, default value in a `match` expression, ju ```scala val i = 4 -val num = i match +val code = i match case 0 => "00" case 1 => "01" case what => s"You gave me: $what" -println(num) +println(code) ``` In this example the variable is named `what` to show that it can be given any legal name. From 426ab70eb2c3e90515a73a4ff1d5cffb3947ccd0 Mon Sep 17 00:00:00 2001 From: Arsenii Chebotarov Date: Wed, 16 Mar 2022 00:19:47 +0200 Subject: [PATCH 3/5] Even more same as Summary. Former removed --- _overviews/scala3-book/methods-most.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index 233c51b847..8f01dc4892 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -383,23 +383,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 From 9182aa8965c929bda381d017d474ed4209bd39af Mon Sep 17 00:00:00 2001 From: Arsenii Chebotarov Date: Wed, 16 Mar 2022 15:35:13 +0200 Subject: [PATCH 4/5] 5 misphrasings and 1 applied theory --- _overviews/scala3-book/methods-most.md | 34 ++++++++++++++--------- _overviews/scala3-book/methods-summary.md | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/_overviews/scala3-book/methods-most.md b/_overviews/scala3-book/methods-most.md index 8f01dc4892..e310dfb0e2 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---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: @@ -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 @@ -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: @@ -279,8 +288,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 nor overridden in subclasses: ```scala class Animal: @@ -288,7 +296,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 +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() @@ -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 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. From e05c24172bbe1fe228f77c492c190b66e6f57b35 Mon Sep 17 00:00:00 2001 From: Arsenii Chebotarov Date: Tue, 29 Mar 2022 21:28:27 +0300 Subject: [PATCH 5/5] some lil bugs --- _overviews/scala3-book/control-structures.md | 4 ++-- _overviews/scala3-book/methods-most.md | 15 +++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/_overviews/scala3-book/control-structures.md b/_overviews/scala3-book/control-structures.md index 186cc34e4d..7015f25c86 100644 --- a/_overviews/scala3-book/control-structures.md +++ b/_overviews/scala3-book/control-structures.md @@ -457,11 +457,11 @@ 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" => s"$name says, Yubba dubba doo" + 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!" -println(speak(Person("Fred"))) // "Fred says, Yubba dubba doo" +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 e310dfb0e2..da050705ec 100644 --- a/_overviews/scala3-book/methods-most.md +++ b/_overviews/scala3-book/methods-most.md @@ -203,7 +203,7 @@ When a method takes no parameters, it’s said to have an _arity_ level of _arit 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---about such methods they say "pure methods" or "pure code", contrary to "dirty" or "impure"---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: @@ -218,16 +218,7 @@ speak // error: "method speak must be called with () argument" speak() // prints "hi" ``` -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. +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 %} @@ -288,7 +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: