You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _ru/tour/higher-order-functions.md
+147-9Lines changed: 147 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -8,34 +8,73 @@ next-page: nested-functions
8
8
previous-page: mixin-class-composition
9
9
---
10
10
11
-
Функции высшего порядка могут принимать другие функции в качестве параметров или возвращать функцию в качестве результата.
12
-
Такое возможно поскольку функции являются объектами первого класса в Scala.
13
-
На текущем этапе терминология может казаться немного запутанной, мы используем следующую фразу "функция высшего порядка" как для методов, так и для функций, которые могут принимать другие функции в качестве параметров, или возвращать функции в качестве результата.
11
+
Функции высшего порядка могут принимать другие функции в качестве параметров или возвращать функцию в качестве результата.
12
+
Такое возможно поскольку функции являются объектами первого класса в Scala.
13
+
На текущем этапе терминология может казаться немного запутанной, мы используем следующую фразу "функция высшего порядка" как для методов, так и для функций, которые могут принимать другие функции в качестве параметров, или возвращать функции в качестве результата.
14
14
15
-
Одним из наиболее распространенных примеров функции высшего порядка
15
+
В чисто объектно-ориентированном мире рекомендуется избегать раскрытия методов,
16
+
параметризованных функциями, которые могут привести к утечке внутреннего состояния объекта.
17
+
Утечка внутреннего состояния может нарушить инварианты самого объекта, тем самым нарушив инкапсуляцию.
18
+
19
+
Одним из наиболее распространенных примеров функции высшего порядка
16
20
является функция `map`, которая доступна в коллекциях Scala.
`doubleSalary` - это функция, которая принимает один Int `x` и возвращает `x * 2`. В общем случае, кортеж (список имен в скобках) слева от стрелки `=>` - это список параметров, а значение выражения следует справа. Это же значение возвращается в качестве результата. В строке 3 к каждому элементу списка зарплат (salaries) применяется функция `doubleSalary`.
23
37
24
38
Чтобы сократить код, мы можем сделать функцию анонимной и передать ее напрямую в качестве аргумента в map:
39
+
40
+
{% tabs map_example_2 %}
41
+
42
+
{% tab 'Scala 2 и 3' for=map_example_2 %}
43
+
25
44
```scala mdoc:nest
26
-
valsalaries=Seq(20000, 70000, 40000)
45
+
valsalaries=Seq(20_000, 70_000, 40_000)
27
46
valnewSalaries= salaries.map(x => x *2) // List(40000, 140000, 80000)
28
47
```
48
+
49
+
{% endtab %}
50
+
51
+
{% endtabs %}
52
+
29
53
Обратите внимание, что в приведенном выше примере `x`не объявлен как `Int`. Это потому, что компилятор может вывести тип, основываясь на типе который ожидает функция map. Еще более элегантным способом написания этого же кода было бы таким:
30
54
55
+
{% tabs map_example_3 %}
56
+
57
+
{% tab 'Scala 2 и 3' for=map_example_3 %}
58
+
31
59
```scala mdoc:nest
32
-
valsalaries=Seq(20000, 70000, 40000)
60
+
valsalaries=Seq(20_000, 70_000, 40_000)
33
61
valnewSalaries= salaries.map(_ *2)
34
62
```
63
+
64
+
{% endtab %}
65
+
66
+
{% endtabs %}
67
+
35
68
Поскольку компилятор Scala уже знает тип параметров (Int), вам нужно только указать правую часть функции. Единственное условие заключается в том, что вместо имени параметра необходимо использовать `_` (в предыдущем примере это было `x`).
36
69
37
70
## Преобразование методов в функции
71
+
38
72
Также возможно передавать методы в качестве аргументов функциям более высокого порядка, поскольку компилятор Scala может преобразовать метод в функцию.
defforecastInFahrenheit:Seq[Double] = temperatures.map(convertCtoF) // <-- передается метод convertCtoF
97
+
```
98
+
99
+
{% endtab %}
100
+
101
+
{% endtabs %}
102
+
47
103
Здесь метод `convertCtoF` передается в `forecastInFahrenheit`. Это возможно, потому что компилятор преобразовывает `convertCtoF` в функцию `x => ConvertCtoF(x)` (примечание: `x` будет сгенерированным именем, которое гарантированно будет уникальным в рамках своей области видимости).
48
104
49
105
## Функции, которые принимают функции
106
+
50
107
Одной из причин использования функций высшего порядка является сокращение избыточного кода. Допустим, вам нужны какие-то методы, которые могли бы повышать чью-то зарплату по разным условиям. Без создания функции высшего порядка это могло бы выглядеть примерно так:
Обратите внимание, что каждый из этих трех методов отличается только коэффициентом умножения. Для упрощения можно перенести повторяющийся код в функцию высшего порядка:
Новый метод, `promotion`, берет зарплату и функцию типа `Double => Double` (т.е. функция, которая берет Double и возвращает Double) и возвращает их произведение.
86
196
197
+
Методы и функции обычно выражают поведение или преобразование данных, поэтому наличие функций,
198
+
которые компонуются на основе других функций, может помочь в создании общих механизмов.
199
+
Эти типовые функции откладывают блокировку всего поведения операции,
200
+
предоставляя клиентам возможность контролировать или дополнительно настраивать части самой операции.
87
201
## Функции, возвращающие функции
88
202
89
203
Есть определенные случаи, когда вы хотите сгенерировать функцию. Вот пример метода, который возвращает функцию.
Обратите внимание, что возвращаемый тип urlBuilder`(String, String) => String`. Это означает, что возвращаемая анонимная функция принимает две строки и возвращает строку. В нашем случае возвращаемая анонимная функция `(endpoint: String, query: String) => s"https://www.example.com/$endpoint?$query"`.
0 commit comments