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

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

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

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)

Ссылки: