Scala 3 — Book

Анонимные функции

Language

Анонимная функция, также известная как лямбда, представляет собой блок кода, который передается в качестве аргумента функции высшего порядка. Википедия определяет анонимную функцию как “определение функции, не привязанное к идентификатору”.

Например, возьмем коллекцию:

val ints = List(1, 2, 3)

Можно создать новый список, удвоив каждый элемент в целых числах, используя метод map класса List и свою пользовательскую анонимную функцию:

val doubledInts = ints.map(_ * 2)   // List(2, 4, 6)

Как видно из комментария, doubleInts содержит список List(2, 4, 6). В этом примере анонимной функцией является часть кода:

_ * 2

Это сокращенный способ сказать: “Умножить данный элемент на 2”.

Более длинные формы

Когда вы освоитесь со Scala, то будете постоянно использовать эту форму для написания анонимных функций, использующих одну переменную в одном месте функции. Но при желании можете также написать их, используя более длинные формы, поэтому в дополнение к написанию этого кода:

val doubledInts = ints.map(_ * 2)

вы также можете написать его, используя такие формы:

val doubledInts = ints.map((i: Int) => i * 2)
val doubledInts = ints.map((i) => i * 2)
val doubledInts = ints.map(i => i * 2)

Все эти строки имеют одно и то же значение: удваивайте каждый элемент ints, чтобы создать новый список, doubledInts (синтаксис каждой формы объясняется ниже).

Если вы знакомы с Java, вам будет полезно узнать, что эти примеры map эквивалентны следующему Java коду:

List<Integer> ints = List.of(1, 2, 3);
List<Integer> doubledInts = ints.stream()
                                .map(i -> i * 2)
                                .collect(Collectors.toList());

Сокращение анонимных функций

Если необходимо явно указать анонимную функцию, можно использовать следующую длинную форму:

val doubledInts = ints.map((i: Int) => i * 2)

Анонимная функция в этом выражении такова:

(i: Int) => i * 2

Если незнаком данный синтаксис, то можно воспринимать символ => как преобразователь, потому что выражение преобразует список параметров в левой части символа (переменная Int с именем i) в новый результат, используя алгоритм справа от символа => (в данном случае выражение, которое удваивает значение Int).

Сокращение выражения

Эту длинную форму можно сократить, как будет показано в следующих шагах. Во-первых, вот снова самая длинная и явная форма:

val doubledInts = ints.map((i: Int) => i * 2)

Поскольку компилятор Scala может сделать вывод из данных в ints о том, что i - это Int, Int объявление можно удалить:

val doubledInts = ints.map((i) => i * 2)

Поскольку есть только один аргумент, круглые скобки вокруг параметра i не нужны:

val doubledInts = ints.map(i => i * 2)

Поскольку Scala позволяет использовать символ _ вместо имени переменной, когда параметр появляется в функции только один раз, код можно упростить еще больше:

val doubledInts = ints.map(_ * 2)

Ещё короче

В других примерах можно еще больше упростить анонимные функции. Например, начиная с самой явной формы, можно распечатать каждый элемент в ints, используя эту анонимную функцию с методом foreach класса List:

ints.foreach((i: Int) => println(i))

Как и раньше, объявление Int не требуется, а поскольку аргумент всего один, скобки вокруг i не нужны:

ints.foreach(i => println(i))

Поскольку i используется в теле функции только один раз, выражение можно еще больше упростить с помощью символа _:

ints.foreach(println(_))

Наконец, если анонимная функция состоит из одного вызова метода с одним аргументом, нет необходимости явно называть и указывать аргумент, можно написать только имя метода (здесь, println):

ints.foreach(println)

Contributors to this page: