Как работает магия метода apply () в Scala?

79

В Scala, если я определяю метод, вызываемый applyв классе или в объекте верхнего уровня, этот метод будет вызываться всякий раз, когда я добавляю пару круглых скобок к экземпляру этого класса и помещаю соответствующие аргументы apply()между ними. Например:

class Foo(x: Int) {
    def apply(y: Int) = {
        x*x + y*y
    }
}

val f = new Foo(3)
f(4)   // returns 25

По сути, object(args)это просто синтаксический сахар для object.apply(args).

Как Scala выполняет это преобразование?

Происходит ли здесь глобально определенное неявное преобразование, подобное неявному преобразованию типов в объекте Predef (но другое по своему характеру)? Или это какая-то более глубокая магия? Я спрашиваю, потому что кажется, что Scala настоятельно поддерживает последовательное применение меньшего набора правил, а не многих правил с множеством исключений. Сначала это кажется мне исключением.

Джефф
источник
1
Отличное объяснение, stackoverflow.com/questions/9737352/#9738862
Мухаммад Хьюеди

Ответы:

67

Я не думаю, что происходит что-то более глубокое, чем то, что вы изначально сказали: это просто синтаксический сахар, посредством которого компилятор преобразуется f(a)в f.apply(a)специальный синтаксический случай.

Это может показаться особым правилом, но лишь некоторые из них (например, с update) допускают использование DSL- подобных конструкций и библиотек.

Oxbow_lakes
источник
4
Я бы добавил «когда fэто объект (включая функции)». Когда fесть метод, такого перевода явно нет.
Алексей Романов
2
@AlexeyRomanov: Ну, если fэто метод, который определен без списка параметров, то f(a)действительно интерпретируется как что-то вроде val _tmp = f; _tmp.apply(a). Но это действительно твердо входит в область «секущихся волос».
Jörg W Mittag
20

На самом деле все наоборот: объект или класс с методом apply - это нормальный случай, а функция - это способ неявно конструировать объект с тем же именем с помощью метода apply. Фактически каждая определяемая вами функция является подобъектом признака Function n (n - количество аргументов).

Обратитесь к разделу 6.6: Функция Приложение о спецификации Scala языка для получения дополнительной информации о теме.

себасго
источник
+1 за изменение спецификации языка Scala. Я добавил правильное местоположение, так как номер вашей страницы устарел.
Александр Мартинс
8

Я спрашиваю, потому что кажется, что Scala настоятельно поддерживает последовательное применение меньшего набора правил, а не многих правил с множеством исключений.

Да. И это правило принадлежит к этому меньшему набору.

Алексей Романов
источник