Зачем делать различие между методами и функциями в Scala?
Я читал о методах и функциях в Scala. Пост Джима и дополнение Даниэля к нему хорошо объясняют, в чем заключаются различия между ними. Вот что я взял с собой:
- функции-это объекты, методы-нет;
- как следствие функции могут передаваться в качестве аргумента, а методы - нет;
- методы могут быть параметризованы по типу, функции - нет;
- методы быстрее.
Я тоже поймите разницу между def
, val
и var
.
Теперь у меня на самом деле два вопроса:
- Почему мы не можем параметризовать метод apply функции для параметризации функции? И
- Почему метод не может быть вызван объектом функции, чтобы работать быстрее? Или вызывающий функцию вызовет исходный метод напрямую?
С нетерпением ждем ваших ответов и заранее большое спасибо!
2 ответа:
1-Параметризующие функции.
Теоретически компилятор может параметризовать тип функции; его можно было бы добавить в качестве функции. Однако это не совсем тривиально, поскольку функции контравариантны в своем аргументе и ковариантны в своем возвращаемом значении:trait Function1[+T,-R] { ... }
Это означает, что другая функция, которая может принимать больше аргументов, считается подклассом (поскольку она может обрабатывать все, что может обрабатывать суперкласс), и если она производит меньший набор результаты, это нормально (так как он также будет подчиняться конструкции суперкласса таким образом). Но как вы кодируете
def fn[A](a: A) = a
В этих рамках? Все дело в том, что возвращаемый тип равен переданному типу, каким бы он ни был. Вам понадобится
Function1[ ThisCanBeAnything, ThisHasToMatch ]
Как тип вашей функции. "Это может быть что угодно" хорошо представлено
Any
, Если вы хотите один тип, но тогда вы можете вернуть что угодно, поскольку исходный тип потерян. Это не означает, что нет никакого способа реализовать но это не очень хорошо вписывается в существующую структуру.2-Скорость функций.
Это очень просто: функция-это методapply
для другого объекта. Вы должны иметь этот объект, чтобы вызвать его метод. Это всегда будет медленнее (или, по крайней мере, не быстрее), чем вызов собственного метода, поскольку у вас уже есть сам.С практической точки зрения, в наши дни JVMs может выполнять очень хорошую работу встраивания функций; часто нет никакой разницы в производительности до тех пор, пока поскольку вы в основном используете свой метод или функцию, а не создаете объект функции снова и снова. Если вы глубоко вложили очень короткие циклы, вы можете обнаружить, что создаете слишком много функций; перемещение их в vals вне вложенных циклов может сэкономить время. Но не беспокойтесь, пока вы не проведете сравнительный анализ и не узнаете, что там есть узкое место; обычно JVM делает правильные вещи.
Подумайте о сигнатуре типа функции. Он явно говорит, какие типы он принимает. Таким образом, параметризация типа apply() будет непоследовательной.
Функция-это объект, который необходимо создать, инициализировать, а затем собрать мусор. Когда вызывается apply (), он должен захватить объект функции в дополнение к родительскому объекту.