2015-05-28 2 views
4

Я только что начал Scala и занимаюсь рабочими листами. Например:Почему методы класса Скала не являются первоклассными гражданами?

def merp(str: String) : String = s"Merrrrrrrp $str" 
val merp2 = (str: String) => s"Merrrrrrrp $str" 
val merp3 = (str: String) => merp(str) 
val merp4 = merp _ 
merp("rjkghleghe") 
merp4("rjkghleghe") 

и соответствующие результаты рабочего листа:

merp: merp[](val str: String) => String 
merp2: String => String = <function1> 
merp3: String => String = <function1> 
merp4: String => String = <function1> 
res0: String = Merrrrrrrp rjkghleghe 
res1: String = Merrrrrrrp rjkghleghe 

Говоря, например, val merp5 = merp выдает ошибку, потому что по-видимому методы не могут быть значения как функции могут. Но я все еще могу передавать методы в качестве аргументов. Я демонстрирую это в следующем фрагменте кода, адаптировано из a similar SO question: результат

def intCombiner(a: Int, b: Int) : String = s"herrrrrrp $a derrrrrrp $b" 
def etaAbstractor[A, B](combineFoo: (A, B) ⇒ String, a: A, b: B) = combineFoo(a, b) 
etaAbstractor(intCombiner, 15, 16) 

лист:

intCombiner: intCombiner[](val a: Int,val b: Int) => String 
etaAbstractor: etaAbstractor[A,B](val combineFoo: (A, B) => String,val a: A,val b: B) => String 
res10: String = herrrrrrp 15 derrrrrrp 16 

  1. Есть методы, не-бытие первого класса ограничение, может быть наложен путем взаимодействия JVM Scala или это решение в дизайне языка?
  2. Зачем мне скатывать свой собственный eta abstractions, как в ?
  3. Есть merp4 также eta abstraction, или это что-то скрытно похоже?
  4. Почему мой etaAbstractor работает? Скала спокойно заменяет intCombinerintCombiner _?

Теоретические ответы на компьютерные науки приветствуются, как и указатели на любые соответствующие точки в language specification. Благодаря!

+0

Разработка и реализация Scala * является * тесно связана с совместимостью/JVM Java во многих областях - я абсолютно уверен, что это будет тоньше разница без такового, но вы» d должен спросить Мартина (я думаю, он иногда посещает SO) или находят некоторые более ранние заметки. Хотя их можно легко «продвигать» с помощью 'method _'. – user2864740

ответ

3

Отказ от ответственности: Я не ученый, но я попробую угадать:

  1. метод является частью объекта и не существует вне его. Вы не можете передавать метод в одиночку. Закрытие - это другой (эквивалентный?) Способ инкапсулирования состояния, путем преобразования метода объекта в автономную функцию (которая, кстати, представляет собой еще один объект с методом apply() в Scala), вы создаете закрытие. Этот процесс известен как eta-расширение. §3.3.1, §6.26.5

  2. Вам не обязательно. Вы также можете написать val merp3 : (String => String) = merp. §6.26.5

  3. Да, merp4 - это тоже расширение.§6.7

  4. §6.26.2

+1

У Python и JavaScript есть методы, которые * являются * первоклассными функциями, поэтому # 1 есть «В Scala (и Java) ..». – user2864740

+0

@ user2864740 В неподходящем методе Python нельзя вызывать, поэтому он не выглядит как функция первого класса. Привязка связанного метода выглядит как eta-расширение под капотом. Javascript имеет ту же проблему, если вы используете 'this' внутри вашей функции, только вместо ошибки вы будете иметь' undefined' как значение 'this'. –

+0

Все еще остается, что методы являются * не * первоклассными значениями, а скорее являются «проявлениями определений», которые вызывается по имени (или [передача сообщений OO] (http://www.desy.de/gna/html /cc/Tutorial/node5.htm#SECTION00540000000000000000)). Поддержание контекста (или нет) не влияет на их статус гражданства: или фундаментальные различия в реализации. – user2864740

2

Причина, по которой он работает с etaAbstractor, заключается в том, что компилятор может сделать вывод о том, что требуется функция (а не вызов функции).

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

В JVM метод не является объектом, тогда как функция первого класса должна быть одной. Поэтому метод должен быть помещен в объект, чтобы преобразовать его в функцию.

Смежные вопросы