Анонимная функция, также известная как лямбда, представляет собой блок кода, который передается в качестве аргумента функции высшего порядка. Википедия определяет анонимную функцию как “определение функции, не привязанное к идентификатору”.
Например, возьмем коллекцию:
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:
Contents
- Введение
- Возможности Scala
- Почему Scala 3?
- Почувствуй Scala
- Пример 'Hello, World!'
- REPL
- Переменные и типы данных
- Структуры управления
- Моделирование данных
- Методы
- Функции первого класса
- Одноэлементные объекты
- Коллекции
- Контекстные абстракции
- Верхнеуровневые определения
- Обзор
- Первый взгляд на типы
- Интерполяция строк
- Структуры управления
- Моделирование предметной области
- Инструменты
- Моделирование ООП
- Моделирование ФП
- Методы
- Особенности методов
- Main методы в Scala 3
- Обзор
- Функции
- Анонимные функции
- Параметры функции
- Eta расширение
- Функции высшего порядка
- Собственный map
- Создание метода, возвращающего функцию
- Обзор
- Пакеты и импорт
- Коллекции в Scala
- Типы коллекций
- Методы в коллекциях
- Обзор
- Функциональное программирование
- Что такое функциональное программирование?
- Неизменяемые значения
- Чистые функции
- Функции — это значения
- Функциональная обработка ошибок
- Обзор
- Типы и система типов
- Определение типов
- Параметризованные типы
- Пересечение типов
- Объединение типов
- Алгебраические типы данных
- Вариантность
- Непрозрачные типы
- Структурные типы
- Зависимые типы функций
- Другие типы
- Контекстные абстракции
- Методы расширения
- Параметры контекста
- Контекстные границы
- Given импорты
- Классы типов
- Многостороннее равенство
- Неявное преобразование типов
- Обзор
- Параллелизм
- Scala утилиты
- Сборка и тестирование проектов Scala с помощью Sbt
- Рабочие листы
- Взаимодействие с Java