I was comparing two ways of defining a higher-order function in Scala:
def f1(elem: Int)(other: Int) = (elem == other)
def f2(elem: Int) = (other: Int) => (elem == other)
The first one uses currying while the second uses an anonymous function.
I am wondering what is the difference, if any, between the two approaches in terms of how Scala implements them and which version is preferable?
Advantages of Currying Function in Scala One benefit is that Scala currying makes creating anonymous functions easier. Scala Currying also makes it easier to pass around a function as a first-class object. You can keep applying parameters when you find them.
Currying is the process of converting a function with multiple arguments into a sequence of functions that take one argument. Each function returns another function that consumes the following argument.
Currying is a technique of evaluating function with multiple arguments, into sequence of functions with single argument.In other words, when a function, instead of taking all arguments at one time, takes the first one and return a new function that takes the second one and returns a new function which takes the third ...
In Scala, An anonymous function is also known as a function literal. A function which does not contain a name is known as an anonymous function. An anonymous function provides a lightweight function definition. It is useful when we want to create an inline function.
The implementations are quite different to the Scala compiler. The curried version compiles down to a Java method by un-currying the parameters:
def f1(elem: Int, other: Int): Boolean = elem.==(other);
The second version is a method that returns an anonymous function (a Function1
), so their signatures are completely different. Though they can often be used interchangeably within Scala code, there is quite a bit more generated code in the second version:
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>();
()
}
}
I would only consider using the second version in cases where I was explicitly looking to work with Function1
objects. However, I would personally lean towards using the curried version, because you can still get a Function1
back with partial application of the first. The curried version is just as powerful, but won't create Function1
objects when you don't need them.
scala> f1(1) _
res1: Int => Boolean = <function1>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With