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

我在斯卡拉如何实现他们而言不知道有什么区别,如果有的话,这两种方法之间的是哪个版本最好?

回答

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

谢谢你的答案。你如何从scala生成java代码?还有,会像'val f3 =(_:Int)==(_:Int); f3.curried'遭受你用'f2'指出的同样的问题? –

+0

您无法真正从Scala生成清晰的Java字节码(但可以生成字节码)。我使用'-Xprint:jvm'在我的答案中生成了代码,这是Scala编译器的最后阶段之一。 'f3.curried'会创建_two_匿名函数而不是一个,所以它会产生比'f2'多的字节码。 –