Если посмотреть на Scaladoc для метода map
в классах коллекций Scala,
то можно увидеть, что метод определен для приема функции:
def map[B](f: (A) => B): List[B]
-----------
Действительно, в Scaladoc сказано: “f
— это функция, применяемая к каждому элементу”.
Но, несмотря на это, каким-то образом в map
можно передать метод, и он все еще работает:
def times10(i: Int) = i * 10 // метод
List(1, 2, 3).map(times10) // List(10,20,30)
Как это работает? Как можно передать метод в map
, который ожидает функцию?
Технология, стоящая за этим, известна как Eta Expansion. Она преобразует выражение типа метода в эквивалентное выражение типа функции, и делает это легко и незаметно.
Различия между методами и функциями
Исторически методы были частью определения класса, хотя в Scala 3 методы могут быть вне классов, такие как определения верхнего уровня и методы расширения.
В отличие от методов, функции сами по себе являются полноценными объектами, что делает их объектами первого класса.
Их синтаксис также отличается. В этом примере показано, как задать метод и функцию, которые выполняют одну и ту же задачу, определяя, является ли заданное целое число четным:
def isEvenMethod(i: Int) = i % 2 == 0 // метод
val isEvenFunction = (i: Int) => i % 2 == 0 // функция
Функция действительно является объектом, поэтому ее можно использовать так же, как и любую другую переменную, например, помещая в список:
val functions = List(isEvenFunction)
И наоборот, технически метод не является объектом, поэтому в Scala 2 метод нельзя было поместить в List
,
по крайней мере, напрямую, как показано в этом примере:
// В этом примере показано сообщение об ошибке в Scala 2
val methods = List(isEvenMethod)
^
error: missing argument list for method isEvenMethod
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `isEvenMethod _` or `isEvenMethod(_)` instead of `isEvenMethod`.
Как показано в этом сообщении об ошибке, в Scala 2 существует ручной способ преобразования метода в функцию, но важной частью для Scala 3 является то, что технология Eta Expansion улучшена, поэтому теперь, когда попытаться использовать метод в качестве переменной, он просто работает — не нужно самостоятельно выполнять ручное преобразование:
val functions = List(isEvenFunction) // работает
val methods = List(isEvenMethod) // работает
Для целей этой вводной книги важно знать следующее:
- Eta Expansion — технология Scala, позволяющая использовать методы так же, как и функции
- Технология была улучшена в Scala 3, чтобы быть почти полностью бесшовной
Дополнительные сведения о том, как это работает, см. на странице Eta Expansion в справочной документации.
Contributors to this page:
Contents
- Введение
- Возможности Scala
- Почему Scala 3?
- Почувствуй Scala
- Пример 'Hello, World!'
- REPL
- Переменные и типы данных
- Структуры управления
- Моделирование данных
- Методы
- Функции первого класса
- Одноэлементные объекты
- Коллекции
- Контекстные абстракции
- Верхнеуровневые определения
- Обзор
- Первый взгляд на типы
- Интерполяция строк
- Структуры управления
- Моделирование предметной области
- Инструменты
- Моделирование ООП
- Моделирование ФП
- Методы
- Особенности методов
- Main методы в Scala 3
- Обзор
- Функции
- Анонимные функции
- Параметры функции
- Eta расширение
- Функции высшего порядка
- Собственный map
- Создание метода, возвращающего функцию
- Обзор
- Пакеты и импорт
- Коллекции в Scala
- Типы коллекций
- Методы в коллекциях
- Обзор
- Функциональное программирование
- Что такое функциональное программирование?
- Неизменяемые значения
- Чистые функции
- Функции — это значения
- Функциональная обработка ошибок
- Обзор
- Типы и система типов
- Определение типов
- Параметризованные типы
- Пересечение типов
- Объединение типов
- Алгебраические типы данных
- Вариантность
- Непрозрачные типы
- Структурные типы
- Зависимые типы функций
- Другие типы
- Контекстные абстракции
- Методы расширения
- Параметры контекста
- Контекстные границы
- Given импорты
- Классы типов
- Многостороннее равенство
- Неявное преобразование типов
- Обзор
- Параллелизм
- Scala утилиты
- Сборка и тестирование проектов Scala с помощью Sbt
- Рабочие листы
- Взаимодействие с Java