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'多的字節碼。 –