Skip to content

Commit c3fd0a3

Browse files
authored
add code tab in _zh-cn/overviews/scala3-book/fun-hofs.md (#2742)
1 parent 36b8244 commit c3fd0a3

File tree

2 files changed

+118
-17
lines changed

2 files changed

+118
-17
lines changed

_overviews/scala3-book/fun-hofs.md

+28-17
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ In Scala, HOFs are possible because functions are first-class values.
1515
As an important note, while we use the common industry term “higher-order function” in this document, in Scala this phrase applies to both *methods* and *functions*.
1616
Thanks to Scala’s [Eta Expansion technology][eta_expansion], they can generally be used in the same places.
1717

18-
19-
2018
## From consumer to creator
2119

2220
In the examples so far in this book you’ve seen how to be a *consumer* of methods that take other functions as input parameters, such as using HOFs like `map` and `filter`.
@@ -32,8 +30,6 @@ In the process you’ll see:
3230

3331
As a beneficial side effect of this discussion, once you’re comfortable with this syntax, you’ll use it to define function parameters, anonymous functions, and function variables, and it also becomes easier to read the Scaladoc for higher-order functions.
3432

35-
36-
3733
## Understanding filter’s Scaladoc
3834

3935
To understand how higher-order functions work, it helps to dig into an example.
@@ -56,21 +52,27 @@ At this point, if you don’t know the purpose of the `filter` method, all you
5652

5753
Looking specifically at the function parameter `p`, this part of `filter`’s description:
5854

55+
{% tabs filter-definition_1 %}
56+
{% tab 'Scala 2 and 3' %}
5957
```scala
6058
p: A => Boolean
6159
```
60+
{% endtab %}
61+
{% endtabs %}
6262

6363
means that whatever function you pass in must take the type `A` as an input parameter and return a `Boolean`.
6464
So if your list is a `List[Int]`, you can replace the generic type `A` with `Int`, and read that signature like this:
6565

66+
{% tabs filter-definition_2 %}
67+
{% tab 'Scala 2 and 3' %}
6668
```scala
6769
p: Int => Boolean
6870
```
71+
{% endtab %}
72+
{% endtabs %}
6973

7074
Because `isEven` has this type---it transforms an input `Int` into a resulting `Boolean`---it can be used with `filter`.
7175

72-
73-
7476
{% comment %}
7577
NOTE: (A low-priority issue): The next several sections can be condensed.
7678
{% endcomment %}
@@ -101,9 +103,13 @@ def sayHello(f: () => Unit): Unit = f()
101103

102104
This portion of the code---the *type signature*---states that `f` is a function, and defines the types of functions the `sayHello` method will accept:
103105

106+
{% tabs sayHello-definition_1 %}
107+
{% tab 'Scala 2 and 3' %}
104108
```scala
105109
f: () => Unit
106110
```
111+
{% endtab %}
112+
{% endtabs %}
107113

108114
Here’s how this works:
109115

@@ -125,7 +131,6 @@ def helloJoe(): Unit = println("Hello, Joe")
125131
{% endtab %}
126132
{% endtabs %}
127133

128-
129134
Because the type signatures match, you can pass `helloJoe` into `sayHello`:
130135

131136
{% tabs sayHello-usage %}
@@ -139,7 +144,6 @@ sayHello(helloJoe) // prints "Hello, Joe"
139144
If you’ve never done this before, congratulations:
140145
You just defined a method named `sayHello` that takes a function as an input parameter, and then invokes that function in its method body.
141146

142-
143147
### sayHello can take many functions
144148

145149
It’s important to know that the beauty of this approach is not that `sayHello` can take *one* function as an input parameter; the beauty is that it can take *any* function that matches `f`’s signature.
@@ -167,8 +171,6 @@ Bonjour, Julien
167171
This is a good start.
168172
The only thing to do now is see a few more examples of how to define different type signatures for function parameters.
169173

170-
171-
172174
## The general syntax for defining function input parameters
173175

174176
In this method:
@@ -183,26 +185,38 @@ def sayHello(f: () => Unit): Unit
183185

184186
We noted that the type signature for `f` is:
185187

188+
{% tabs sayHello-definition-2_1 %}
189+
{% tab 'Scala 2 and 3' %}
186190
```scala
187191
() => Unit
188192
```
193+
{% endtab %}
194+
{% endtabs %}
189195

190196
We know that this means, “a function that takes no input parameters and returns nothing meaningful (given by `Unit`).”
191197

192198
To demonstrate more type signature examples, here’s a function that takes a `String` parameter and returns an `Int`:
193199

200+
{% tabs sayHello-definition-2_2 %}
201+
{% tab 'Scala 2 and 3' %}
194202
```scala
195203
f: String => Int
196204
```
205+
{% endtab %}
206+
{% endtabs %}
197207

198208
What kinds of functions take a string and return an integer?
199209
Functions like “string length” and checksum are two examples.
200210

201211
Similarly, this function takes two `Int` parameters and returns an `Int`:
202212

213+
{% tabs sayHello-definition-2_3 %}
214+
{% tab 'Scala 2 and 3' %}
203215
```scala
204216
f: (Int, Int) => Int
205217
```
218+
{% endtab %}
219+
{% endtabs %}
206220

207221
Can you imagine what sort of functions match that signature?
208222

@@ -220,15 +234,17 @@ def multiply(a: Int, b: Int): Int = a * b
220234

221235
As you can infer from these examples, the general syntax for defining function parameter type signatures is:
222236

237+
{% tabs add-sub-mul-definitions_1 %}
238+
{% tab 'Scala 2 and 3' %}
223239
```scala
224240
variableName: (parameterTypes ...) => returnType
225241
```
242+
{% endtab %}
243+
{% endtabs %}
226244

227245
> Because functional programming is like creating and combining a series of algebraic equations, it’s common to think about types a *lot* when designing functions and applications.
228246
> You might say that you “think in types.”
229247
230-
231-
232248
## Taking a function parameter along with other parameters
233249

234250
For HOFs to be really useful, they also need some data to work on.
@@ -279,11 +295,8 @@ Hello, world
279295
{% endtab %}
280296
{% endtabs %}
281297

282-
283298
Excellent.
284299
The `executeNTimes` method executes the `helloWorld` function three times.
285-
286-
287300
### As many parameters as needed
288301

289302
Your methods can continue to get as complicated as necessary.
@@ -298,7 +311,6 @@ def executeAndPrint(f: (Int, Int) => Int, i: Int, j: Int): Unit =
298311
{% endtab %}
299312
{% endtabs %}
300313

301-
302314
Because these `sum` and `multiply` methods match that type signature, they can be passed into `executeAndPrint` along with two `Int` values:
303315

304316
{% tabs executeAndPrint-usage %}
@@ -313,7 +325,6 @@ executeAndPrint(multiply, 3, 9) // prints 27
313325
{% endtab %}
314326
{% endtabs %}
315327

316-
317328
## Function type signature consistency
318329

319330
A great thing about learning about Scala’s function type signatures is that the syntax you use to define function input parameters is the same syntax you use to write function literals.

0 commit comments

Comments
 (0)