def withLoaner(n: Int) = new {
def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n")
def apply(op: () => String) : String = apply{i: Int => op()}
}
(не уверен, как это связано с шаблоном займа)
Редактировать Небольшое объяснение, как требуется в комментарии.
Не уверен, что ты знаешь и не знаешь о scala и что ты не понимаешь в этом коде.извините, если что я просто излагаю очевидное.
Во-первых, программа scala состоит из признаков / классов (также одноэлементного объекта) и методов.Все, что делается, делается методами (оставляя конструктор в стороне).Функции (в отличие от методов) являются экземплярами (подтипами) различных признаков FunctionN (N количество аргументов).Каждый из них имеет метод apply, который является реальной реализацией.Если вы напишите
val inc = {i: Int => i + 1}
, он будет десагадирован на
val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1}
(определяет анонимный класс, расширяющий Function1
, с данным методом apply и создающим экземпляр)
Таким образом, написание функции имеет гораздо больший вес, чем простой метод.Также у вас не может быть перегрузки (несколько методов с одним и тем же именем, отличающиеся по сигнатуре, только то, что я делал выше), а также использование именованных аргументов или значения по умолчанию для аргументов.
С другой стороны, функции являются значениями первых классов (их можно передавать как аргументы, возвращать как результат), а методы - нет.При необходимости они автоматически преобразуются в функции, однако при этом могут возникать некоторые крайние ситуации.Если метод предназначен исключительно для использования в качестве значения функции, а не для вызова в качестве метода, может быть лучше написать функцию.
Функция f
с ее методом apply
вызывается с f(x)
вместо f.apply(x)
(что тоже работает), потому что функция scala desugars вызывает нотацию для значения (значение, сопровождаемое скобками)и 0 или более аргументов) для вызова метода apply
.f(x)
является синтаксическим сахаром для f.apply(x)
.Это работает независимо от типа f
, не обязательно должен быть одним из FunctionN
.
То, что делается в withLoaner, - это возвращение объекта (анонимного типа, но можно было бы определить класс отдельно и вернуть его экземпляр).У объекта есть два метода apply
, один из которых принимает Int => String
, другой - () => String
.Когда вы делаете withLoaner(n)(f)
, это означает withLoaner(n).apply(f)
.Выбирается подходящий метод применения, если f
имеет правильный тип для одного из них, в противном случае ошибка компиляции.
На всякий случай, если вам интересно, withLoaner(n)
не означает withLoaner.apply(n)
(или никогда не остановится, это может означать withLoaner.apply.apply(n)
), поскольку withLoaner - это метод, а не значение.