Scala 中的柯里化与匿名函数
Currying vs. anonymous function in Scala
我比较了在 Scala 中定义 higher-order function 的两种方式:
def f1(elem: Int)(other: Int) = (elem == other)
def f2(elem: Int) = (other: Int) => (elem == other)
第一个使用currying while the second uses an anonymous function.
我想知道这两种方法在 Scala 如何实现它们以及哪个版本更可取方面有什么区别?
实现与 Scala 编译器有很大不同。柯里化版本通过 un-currying 参数编译为 Java 方法:
def f1(elem: Int, other: Int): Boolean = elem.==(other);
第二个版本是returns一个匿名函数(一个Function1
)的方法,所以他们的签名是完全不同的。虽然它们通常可以在 Scala 代码中互换使用,但在第二个版本中生成的代码要多得多:
def f2(elem: Int): Function1 = (new <$anon: Function1>(elem): Function1);
@SerialVersionUID(value = 0) final <synthetic> class anonfun$f2 extends scala.runtime.AbstractFunction1$mcZI$sp with Serializable {
final def apply(other: Int): Boolean = anonfun$f2.this.apply$mcZI$sp(other);
<specialized> def apply$mcZI$sp(other: Int): Boolean = anonfun$f2.this.elem.==(other);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Boolean.box(anonfun$f2.this.apply(scala.Int.unbox(v1)));
<synthetic> <paramaccessor> private[this] val elem: Int = _;
def <init>(elem: Int): <$anon: Function1> = {
anonfun$f2.this.elem = elem;
anonfun$f2.super.<init>();
()
}
}
只有在我明确希望使用 Function1
对象的情况下,我才会 考虑 使用第二个版本。但是,我个人倾向于使用 curried 版本,因为您仍然可以通过部分应用第一个版本获得 Function1
回报。柯里化版本同样强大,但不会在您不需要时创建 Function1
对象。
scala> f1(1) _
res1: Int => Boolean = <function1>
我比较了在 Scala 中定义 higher-order function 的两种方式:
def f1(elem: Int)(other: Int) = (elem == other)
def f2(elem: Int) = (other: Int) => (elem == other)
第一个使用currying while the second uses an anonymous function.
我想知道这两种方法在 Scala 如何实现它们以及哪个版本更可取方面有什么区别?
实现与 Scala 编译器有很大不同。柯里化版本通过 un-currying 参数编译为 Java 方法:
def f1(elem: Int, other: Int): Boolean = elem.==(other);
第二个版本是returns一个匿名函数(一个Function1
)的方法,所以他们的签名是完全不同的。虽然它们通常可以在 Scala 代码中互换使用,但在第二个版本中生成的代码要多得多:
def f2(elem: Int): Function1 = (new <$anon: Function1>(elem): Function1);
@SerialVersionUID(value = 0) final <synthetic> class anonfun$f2 extends scala.runtime.AbstractFunction1$mcZI$sp with Serializable {
final def apply(other: Int): Boolean = anonfun$f2.this.apply$mcZI$sp(other);
<specialized> def apply$mcZI$sp(other: Int): Boolean = anonfun$f2.this.elem.==(other);
final <bridge> <artifact> def apply(v1: Object): Object = scala.Boolean.box(anonfun$f2.this.apply(scala.Int.unbox(v1)));
<synthetic> <paramaccessor> private[this] val elem: Int = _;
def <init>(elem: Int): <$anon: Function1> = {
anonfun$f2.this.elem = elem;
anonfun$f2.super.<init>();
()
}
}
只有在我明确希望使用 Function1
对象的情况下,我才会 考虑 使用第二个版本。但是,我个人倾向于使用 curried 版本,因为您仍然可以通过部分应用第一个版本获得 Function1
回报。柯里化版本同样强大,但不会在您不需要时创建 Function1
对象。
scala> f1(1) _
res1: Int => Boolean = <function1>