Зачем делать различие между методами и функциями в Scala?


Я читал о методах и функциях в Scala. Пост Джима и дополнение Даниэля к нему хорошо объясняют, в чем заключаются различия между ними. Вот что я взял с собой:

  • функции-это объекты, методы-нет;
  • как следствие функции могут передаваться в качестве аргумента, а методы - нет;
  • методы могут быть параметризованы по типу, функции - нет;
  • методы быстрее.

Я тоже поймите разницу между def, val и var.

Теперь у меня на самом деле два вопроса:

  1. Почему мы не можем параметризовать метод apply функции для параметризации функции? И
  2. Почему метод не может быть вызван объектом функции, чтобы работать быстрее? Или вызывающий функцию вызовет исходный метод напрямую?

С нетерпением ждем ваших ответов и заранее большое спасибо!

2   4  

2 ответа:

1-Параметризующие функции.

Теоретически компилятор может параметризовать тип функции; его можно было бы добавить в качестве функции. Однако это не совсем тривиально, поскольку функции контравариантны в своем аргументе и ковариантны в своем возвращаемом значении:
trait Function1[+T,-R] { ... }

Это означает, что другая функция, которая может принимать больше аргументов, считается подклассом (поскольку она может обрабатывать все, что может обрабатывать суперкласс), и если она производит меньший набор результаты, это нормально (так как он также будет подчиняться конструкции суперкласса таким образом). Но как вы кодируете

def fn[A](a: A) = a

В этих рамках? Все дело в том, что возвращаемый тип равен переданному типу, каким бы он ни был. Вам понадобится

Function1[ ThisCanBeAnything, ThisHasToMatch ]

Как тип вашей функции. "Это может быть что угодно" хорошо представлено Any, Если вы хотите один тип, но тогда вы можете вернуть что угодно, поскольку исходный тип потерян. Это не означает, что нет никакого способа реализовать но это не очень хорошо вписывается в существующую структуру.

2-Скорость функций.

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

С практической точки зрения, в наши дни JVMs может выполнять очень хорошую работу встраивания функций; часто нет никакой разницы в производительности до тех пор, пока поскольку вы в основном используете свой метод или функцию, а не создаете объект функции снова и снова. Если вы глубоко вложили очень короткие циклы, вы можете обнаружить, что создаете слишком много функций; перемещение их в vals вне вложенных циклов может сэкономить время. Но не беспокойтесь, пока вы не проведете сравнительный анализ и не узнаете, что там есть узкое место; обычно JVM делает правильные вещи.

Подумайте о сигнатуре типа функции. Он явно говорит, какие типы он принимает. Таким образом, параметризация типа apply() будет непоследовательной.

Функция-это объект, который необходимо создать, инициализировать, а затем собрать мусор. Когда вызывается apply (), он должен захватить объект функции в дополнение к родительскому объекту.