Анонимные функции
Анонимная функция, также называемая лямбда, представляет собой блок кода, который передается в качестве аргумента функции более высокого порядка. Википедия определяет анонимную функцию как "определение функции, не привязанное к идентификатору".
Например, возьмем коллекцию:
val ints = List(1, 2, 3)
Можно создать новый список, удвоив каждый элемент в целых числах,
используя метод map
класса List
и свою пользовательскую анонимную функцию:
val doubledInts = ints.map(_ * 2)
// doubledInts: List[Int] = List(2, 4, 6)
Как видно из комментария, doubleInts
содержит список List(2, 4, 6)
.
В этом примере анонимной функцией является часть кода: _ * 2
.
Это сокращенный способ сказать: "Умножить данный элемент на 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
.
Сокращение анонимных функций
Если необходимо явно указать анонимную функцию, можно использовать эту длинную форму:
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)
Ещё короче
В других примерах можно еще больше упростить анонимные функции.
Например, начиная с самой явной формы, можно распечатать каждый элемент в целых числах,
используя эту анонимную функцию с методом foreach
класса List
:
ints.foreach((i: Int) => println(i))
Как и раньше, объявление Int
не требуется, а поскольку аргумент всего один, скобки вокруг i
не нужны:
ints.foreach(i => println(i))
Поскольку i
используется в теле функции только один раз, выражение можно еще больше упростить с помощью символа _
:
ints.foreach(println(_))
Наконец, если анонимная функция состоит из одного вызова метода с одним аргументом,
нет необходимости явно называть и указывать аргумент, можно написать только имя метода (здесь, println
):
ints.foreach(println)
Ссылки: