3

я сравнивал два способа определения в Scala в higher-order function:Карринг против анонимной функции в Scala

def f1(elem: Int)(other: Int) = (elem == other) 

def f2(elem: Int) = (other: Int) => (elem == other) 

Первый использует currying в то время как второй использует anonymous function.

Мне интересно, какая разница, если таковая имеется, между двумя подходами в плане того, как Scala реализует их и какая версия предпочтительнее?

ответ

7

Реализации сильно отличаются от компилятора Scala. Кэрри версия компилирует к методу Java, убрав выделки параметров:

def f1(elem: Int, other: Int): Boolean = elem.==(other); 

вторая версия представляет собой метод, который возвращает анонимную функцию (а Function1), поэтому их подписи совершенно различны. Хотя они часто могут быть взаимозаменяемыми в Scala кода, есть немного больше сгенерированный код во второй версии:

def f2(elem: Int): Function1 = (new <$anon: Function1>(elem): Function1); 

    @SerialVersionUID(value = 0) final <synthetic> class anonfun$f2$1 extends scala.runtime.AbstractFunction1$mcZI$sp with Serializable { 
    final def apply(other: Int): Boolean = anonfun$f2$1.this.apply$mcZI$sp(other); 
    <specialized> def apply$mcZI$sp(other: Int): Boolean = anonfun$f2$1.this.elem$1.==(other); 
    final <bridge> <artifact> def apply(v1: Object): Object = scala.Boolean.box(anonfun$f2$1.this.apply(scala.Int.unbox(v1))); 
    <synthetic> <paramaccessor> private[this] val elem$1: Int = _; 
    def <init>(elem$1: Int): <$anon: Function1> = { 
     anonfun$f2$1.this.elem$1 = elem$1; 
     anonfun$f2$1.super.<init>(); 
    () 
    } 
    } 

Я бы только рассмотреть используя второй вариант в тех случаях, когда я был явно ищу работу с Function1 объектов. Тем не менее, я лично склоняюсь к использованию версии в карри, потому что вы все равно можете получить Function1 назад с частичным применением первого. Версия в карри также столь же мощна, но не создаст объекты Function1, когда они вам не понадобятся.

scala> f1(1) _ 
res1: Int => Boolean = <function1> 
+0

благодарим за ответ. как вы производите Java-код из scala? также, что-то вроде 'val f3 = (_: Int) == (_: Int); f3.curried' страдают от той же проблемы, которую вы отметили с помощью 'f2'? –

+0

Вы не можете создать четкий байт-код Java из Scala (но может генерировать байтовый код). Я использовал '-Xprint: jvm' для создания кода в моем ответе, который является одной из последних фаз компилятора Scala. 'f3.curried' создавал бы _two_ анонимные функции вместо одного, поэтому он выдавал бы более байт-код, чем' f2'. –

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