Вернемся к примеру из предыдущего раздела:
val doubledInts = ints.map((i: Int) => i * 2)
Анонимной функцией является следующая часть:
(i: Int) => i * 2
Причина, по которой она называется анонимной (anonymous), заключается в том, что она не присваивается переменной и, следовательно, не имеет имени.
Однако анонимная функция, также известная как функциональный литерал (function literal), может быть назначена переменной для создания функциональной переменной (function variable):
val double = (i: Int) => i * 2
Код выше создает функциональную переменную с именем double
.
В этом выражении исходный литерал функции находится справа от символа =
:
val double = (i: Int) => i * 2
-----------------
, а новое имя переменной - слева:
val double = (i: Int) => i * 2
------
список параметров функции подчеркнут:
val double = (i: Int) => i * 2
--------
Как и список параметров для метода, список параметров функции означает,
что функция double
принимает один параметр с типом Int
и именем i
.
Как можно видеть ниже, double
имеет тип Int => Int
,
что означает, что он принимает один параметр Int
и возвращает Int
:
scala> val double = (i: Int) => i * 2
val double: Int => Int = ...
Вызов функции
Функция double
может быть вызвана так:
val x = double(2) // 4
double
также можно передать в вызов map
:
List(1, 2, 3).map(double) // List(2, 4, 6)
Кроме того, когда есть другие функции типа Int => Int
:
val triple = (i: Int) => i * 3
можно сохранить их в List
или Map
:
val functionList = List(double, triple)
val functionMap = Map(
"2x" -> double,
"3x" -> triple
)
Если вы вставите эти выражения в REPL, то увидите, что они имеют следующие типы:
// список, содержащий функции типа `Int => Int`
functionList: List[Int => Int]
// Map, ключи которой имеют тип `String`,
// а значения имеют тип `Int => Int`
functionMap: Map[String, Int => Int]
Ключевые моменты
Ключевыми моментами здесь являются:
- чтобы создать функциональную переменную, достаточно присвоить имя переменной функциональному литералу
- когда есть функция, с ней можно обращаться как с любой другой переменной, то есть как со
String
илиInt
переменной
А благодаря улучшенной функциональности Eta Expansion в Scala 3 с методами можно обращаться точно так же.
Contributors to this page:
Contents
- Введение
- Возможности Scala
- Почему Scala 3?
- Почувствуй Scala
- Пример 'Hello, World!'
- REPL
- Переменные и типы данных
- Структуры управления
- Моделирование данных
- Методы
- Функции первого класса
- Одноэлементные объекты
- Коллекции
- Контекстные абстракции
- Верхнеуровневые определения
- Обзор
- Первый взгляд на типы
- Интерполяция строк
- Структуры управления
- Моделирование предметной области
- Инструменты
- Моделирование ООП
- Моделирование ФП
- Методы
- Особенности методов
- Main методы в Scala 3
- Обзор
- Функции
- Анонимные функции
- Параметры функции
- Eta расширение
- Функции высшего порядка
- Собственный map
- Создание метода, возвращающего функцию
- Обзор
- Пакеты и импорт
- Коллекции в Scala
- Типы коллекций
- Методы в коллекциях
- Обзор
- Функциональное программирование
- Что такое функциональное программирование?
- Неизменяемые значения
- Чистые функции
- Функции — это значения
- Функциональная обработка ошибок
- Обзор
- Типы и система типов
- Определение типов
- Параметризованные типы
- Пересечение типов
- Объединение типов
- Алгебраические типы данных
- Вариантность
- Непрозрачные типы
- Структурные типы
- Зависимые типы функций
- Другие типы
- Контекстные абстракции
- Методы расширения
- Параметры контекста
- Контекстные границы
- Given импорты
- Классы типов
- Многостороннее равенство
- Неявное преобразование типов
- Обзор
- Параллелизм
- Scala утилиты
- Сборка и тестирование проектов Scala с помощью Sbt
- Рабочие листы
- Взаимодействие с Java