Partially applied functions in Scala

Before going into Partially applied Functions, let me introduces 2 terms-
Function Literal- This exists in the source code- Something similar to Class definition. So we have

(x:Int,y:Int) => x+y

Function value- When this function literal is assigned to a reference they become function values. The are similar to the Objects created from the class. These are created at runtime

var sum = (x:Int,y:Int) => x+y

So in the above case we can use sum to invoke the method.

println(sum(5,7))

So coming to the partially applied functions- We always pass all the arguments while invoking the method. But in Scala we can pass some of the arguments defined in the function there by creating a partially applied function. So the rest of the arguments can be passed when the function is being invoked. Lets have a look at an example before going into detail of how its implemented.

object PartialFunction extends Application
{
  def sum(a:Int,b:Int,c:Int) = a+b+c
  val partial1 = sum _
  val partial2 = sum(1,_:Int,8)
  println("Partial 1: "+partial1(5,6,7))
  println("Partial 2: "+partial2(4))
}

The output would be:

C:devscalapartial>fsc PartialFunction.scala

C:devscalapartial>scala PartialFunction
Partial 1: 18
Partial 2: 13

Lets pay attention to the line-4 and line-5 above. With

val partial1 = sum _ 

we say that the arguments would be supplied later on, when its invoked using partial1. With

val partial2 = sum(1,_:Int,8)

we are providing 2 arguments now and the third one would be provided when invoked using partial2. In each of the above 2 line- A function value object is created which is of type- Function3 (for partial1) and Function1(for partial2). FunctionN is a trait with an apply method with N parameters. So Function1 means- an apply method with 1 parameter and so on. Now that we have the function values- we invoke them by passing required arguments.

Lets look what methods does the class file generate-

C:devscalapartial>javap PartialFunction
Compiled from "PartialFunction.scala"
public final class PartialFunction extends java.lang.Object{
    public static final void main(java.lang.String[]);
    public static final void scala$Application$_setter_$executionStart_$eq(long);
    public static final long executionStart();
    public static final scala.Function1 partial2();
    public static final scala.Function3 partial1();
    public static final int sum(int, int, int);
}

So we can see 2 methods there- partial2() and partial1(). We might be surprised to see that they arent taking any arguments. But in our example above we have passed arguments to these function values. So there’s something wrong?? No, there’s nothing wrong. If we look at the return type for partial1 and partial2 its Function3 and Function1 respectively. And when you compile the scala code shown in the beginning, you get 2 more class files generated:

C:devscalapartial>ls
PartialFunction$$anonfun$1.class
PartialFunction$$anonfun$2.class

And when inspected these classes, the following could be seen

C:devscalapartial>javap PartialFunction$$anonfun$1
Compiled from "PartialFunction.scala"
public final class PartialFunction$$anonfun$1 extends scala.runtime.AbstractFunction1$mcII$sp implements java.io.Serializable{
    public static final long serialVersionUID;
    public static {};
    public final int apply(int);
    public int apply$mcII$sp(int);
    public final java.lang.Object apply(java.lang.Object);
    public PartialFunction$$anonfun$1();
}

You can see that class extends scala.runtime.AbstractFunction1(this actually extends Function1). So PartialFunction$$anonfun$1 IS-A Function1. You can also see an apply method with one argument- the missing argument in the function value. So we are actually invoking this apply method. Same goes with the other class as well:

C:devscalapartial>javap PartialFunction$$anonfun$2
Compiled from "PartialFunction.scala"
public final class PartialFunction$$anonfun$2 extends scala.runtime.AbstractFunction3 implements java.io.Serializable{
    public static final long serialVersionUID;
    public static {};
    public final int apply(int, int, int);
    public final java.lang.Object apply(java.lang.Object, java.lang.Object, java.lang.Object);
    public PartialFunction$$anonfun$2();
}

Note that the above apply() takes three arguments/complete argument list.This indicates that the function(partial1) doesnt not take any arguments when creating a function value of sum function.

I had asked a query on Stackoverflow regarding the advantages of using Partially Applied functions. So this is what I could get from the replies there:

Although you can’t assign a method or nested function to a variable, or pass it as an argument to another function, you can do these things if you wrap the method or nested function in a function value by placing an underscore after its name.

4 thoughts on “Partially applied functions in Scala”

    • Scala is a programming language which runs on JVM just like Java- but it is based on the Functional and Object oriented paradigm. Even I have been learning this from a very long tie- difficult to get pick the Functional programming style. You can visit http://www.scala-lang.org for more information.

      Reply

Leave a Reply

Discover more from Experiences Unlimited

Subscribe now to keep reading and get access to the full archive.

Continue reading