Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Currying vs. anonymous function in Scala

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?

like image 847
Rodrigue Avatar asked Feb 11 '17 19:02

Rodrigue


People also ask

What is the advantage of currying in Scala?

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.

What is currying in spark?

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.

What is currying explain it with example?

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 ...

What is anonymous class in Scala?

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.


1 Answers

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>
like image 190
Michael Zajac Avatar answered Sep 28 '22 16:09

Michael Zajac