From 518d779c319189d0dbf6281aa288dac2c1d7a4b9 Mon Sep 17 00:00:00 2001 From: Doehyun Baek Date: Sun, 1 Jan 2023 11:16:52 +0900 Subject: [PATCH 1/3] Add code tabs to fun-write-method-returns-function --- .../fun-write-method-returns-function.md | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/_overviews/scala3-book/fun-write-method-returns-function.md b/_overviews/scala3-book/fun-write-method-returns-function.md index eb2bb039a1..79795089ea 100644 --- a/_overviews/scala3-book/fun-write-method-returns-function.md +++ b/_overviews/scala3-book/fun-write-method-returns-function.md @@ -20,48 +20,72 @@ Once again we start with a problem statement: Given that statement, you can start building `greet`. You know it’s going to be a method: +{% tabs fun-write-method-returns-function-1 %} +{% tab 'Scala 2 and 3' %} ```scala def greet() ``` +{% endtab %} +{% endtabs %} You also know this method will return a function that (a) takes a `String` parameter, and (b) prints that string using `println`. Therefore that function has the type, `String => Unit`: +{% tabs fun-write-method-returns-function-2 %} +{% tab 'Scala 2 and 3' %} ```scala def greet(): String => Unit = ??? ---------------- ``` +{% endtab %} +{% endtabs %} Now you just need a method body. You know that the method needs to return a function, and that function takes a `String` and prints it. This anonymous function matches that description: +{% tabs fun-write-method-returns-function-3 %} +{% tab 'Scala 2 and 3' %} ```scala (name: String) => println(s"Hello, $name") ``` +{% endtab %} +{% endtabs %} Now you just return that function from the method: +{% tabs fun-write-method-returns-function-4 %} +{% tab 'Scala 2 and 3' %} ```scala // a method that returns a function def greet(): String => Unit = (name: String) => println(s"Hello, $name") ``` +{% endtab %} +{% endtabs %} Because this method returns a function, you get the function by calling `greet()`. This is a good step to do in the REPL because it verifies the type of the new function: +{% tabs fun-write-method-returns-function-5 %} +{% tab 'Scala 2 and 3' %} ```` scala> val greetFunction = greet() val greetFunction: String => Unit = Lambda.... ----------------------------- ```` +{% endtab %} +{% endtabs %} Now you can call `greetFunction`: +{% tabs fun-write-method-returns-function-6 %} +{% tab 'Scala 2 and 3' %} ```scala greetFunction("Joe") // prints "Hello, Joe" ``` +{% endtab %} +{% endtabs %} Congratulations, you just created a method that returns a function, and then executed that function. @@ -72,29 +96,43 @@ Congratulations, you just created a method that returns a function, and then exe Our method would be more useful if you could pass in a greeting, so let’s do that. All you have to do is pass the greeting in as a parameter to the `greet` method, and use it in the string inside `println`: +{% tabs fun-write-method-returns-function-7 %} +{% tab 'Scala 2 and 3' %} ```scala def greet(theGreeting: String): String => Unit = (name: String) => println(s"$theGreeting, $name") ``` +{% endtab %} +{% endtabs %} Now when you call your method, the process is more flexible because you can change the greeting. This is what it looks like when you create a function from this method: +{% tabs fun-write-method-returns-function-8 %} +{% tab 'Scala 2 and 3' %} ```` scala> val sayHello = greet("Hello") val sayHello: String => Unit = Lambda..... ------------------------ ```` +{% endtab %} +{% endtabs %} The REPL type signature output shows that `sayHello` is a function that takes a `String` input parameter and returns `Unit` (nothing). So now when you give `sayHello` a `String`, it prints the greeting: +{% tabs fun-write-method-returns-function-9 %} +{% tab 'Scala 2 and 3' %} ```scala sayHello("Joe") // prints "Hello, Joe" ``` +{% endtab %} +{% endtabs %} You can also change the greeting to create new functions, as desired: +{% tabs fun-write-method-returns-function-10 %} +{% tab 'Scala 2 and 3' %} ```scala val sayCiao = greet("Ciao") val sayHola = greet("Hola") @@ -102,6 +140,8 @@ val sayHola = greet("Hola") sayCiao("Isabella") // prints "Ciao, Isabella" sayHola("Carlos") // prints "Hola, Carlos" ``` +{% endtab %} +{% endtabs %} @@ -116,27 +156,53 @@ A first thing you know is that you want to create a method that (a) takes a “d Furthermore, because that function prints a string that it’s given, you know it has the type `String => Unit`. With that information you write the method signature: +{% tabs fun-write-method-returns-function-11 %} +{% tab 'Scala 2 and 3' %} ```scala def createGreetingFunction(desiredLanguage: String): String => Unit = ??? ``` +{% endtab %} +{% endtabs %} Next, because you know that the possible functions you’ll return take a string and print it, you can write two anonymous functions for the English and French languages: +{% tabs fun-write-method-returns-function-12 %} +{% tab 'Scala 2 and 3' %} ```scala (name: String) => println(s"Hello, $name") (name: String) => println(s"Bonjour, $name") ``` +{% endtab %} +{% endtabs %} Inside a method it might be a little more readable if you give those anonymous functions some names, so let’s assign them to two variables: +{% tabs fun-write-method-returns-function-13 %} +{% tab 'Scala 2 and 3' %} ```scala val englishGreeting = (name: String) => println(s"Hello, $name") val frenchGreeting = (name: String) => println(s"Bonjour, $name") ``` +{% endtab %} +{% endtabs %} Now all you need to do is (a) return `englishGreeting` if the `desiredLanguage` is English, and (b) return `frenchGreeting` if the `desiredLanguage` is French. One way to do that is with a `match` expression: +{% tabs fun-write-method-returns-function-14 class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +def createGreetingFunction(desiredLanguage: String): String => Unit = { + val englishGreeting = (name: String) => println(s"Hello, $name") + val frenchGreeting = (name: String) => println(s"Bonjour, $name") + desiredLanguage match { + case "english" => englishGreeting + case "french" => frenchGreeting + } +} +``` +{% endtab %} +{% tab 'Scala 3' %} ```scala def createGreetingFunction(desiredLanguage: String): String => Unit = val englishGreeting = (name: String) => println(s"Hello, $name") @@ -145,23 +211,33 @@ def createGreetingFunction(desiredLanguage: String): String => Unit = case "english" => englishGreeting case "french" => frenchGreeting ``` +{% endtab %} +{% endtabs %} And that’s the final method. Notice that returning a function value from a method is no different than returning a string or integer value. This is how `createGreetingFunction` builds a French-greeting function: +{% tabs fun-write-method-returns-function-15 %} +{% tab 'Scala 2 and 3' %} ```scala val greetInFrench = createGreetingFunction("french") greetInFrench("Jonathan") // prints "Bonjour, Jonathan" ``` +{% endtab %} +{% endtabs %} And this is how it builds an English-greeting function: +{% tabs fun-write-method-returns-function-16 %} +{% tab 'Scala 2 and 3' %} ```scala val greetInEnglish = createGreetingFunction("english") greetInEnglish("Joe") // prints "Hello, Joe" ``` +{% endtab %} +{% endtabs %} If you’re comfortable with that code---congratulations---you now know how to write methods that return functions. From 9919393775bb976e354a1793da3baa8ef869d53a Mon Sep 17 00:00:00 2001 From: Doehyun Baek Date: Thu, 5 Jan 2023 19:42:15 +0900 Subject: [PATCH 2/3] Update Gemfile.lock --- Gemfile.lock | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6db1272f39..dfc8d86b1d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -54,6 +54,8 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.4.0) + nokogiri (1.13.10-arm64-darwin) + racc (~> 1.4) nokogiri (1.13.10-x86_64-darwin) racc (~> 1.4) nokogiri (1.13.10-x86_64-linux) @@ -81,6 +83,7 @@ GEM yell (2.2.2) PLATFORMS + arm64-darwin-22 x86_64-darwin-21 x86_64-linux @@ -91,4 +94,4 @@ DEPENDENCIES webrick (~> 1.7) BUNDLED WITH - 2.3.10 + 2.4.2 From fc15ab3079958eb8354833bf980d39dab2f7be36 Mon Sep 17 00:00:00 2001 From: Doehyun Baek Date: Thu, 5 Jan 2023 22:13:44 +0900 Subject: [PATCH 3/3] Revert bundler version change --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index dfc8d86b1d..4765006422 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,4 +94,4 @@ DEPENDENCIES webrick (~> 1.7) BUNDLED WITH - 2.4.2 + 2.3.10