Scala Placeholder Syntax

In our earlier discussions, we learned that Scala functions offer automatic type inference. Scala type inference works at different places. Two of the most common examples are following.

  1. Value declaration
  2. Function's return type

Sometimes we do not realize it, but Scala type inference also works with the inline function values. Let's try to understand it with some examples.

                                        
    //Define a range
    val r = 1 to 5
    //r: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)

    //Option 1 - define a function value and then pass it 
    val f = (x:Int) => x + 10
    //f: Int => Int = <function1>
    r.map(f)
    //res2: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15)

    //Option 2 - pass an inline function value as a single step
    r.map(x => x + 10)
    //res0: scala.collection.immutable.IndexedSeq[Int] = Vector(11, 12, 13, 14, 15)
                                    

The first line of the above code defines a Scala range. We want to apply the map method on that range. We know that the map method is a Higher Order function, and it takes a function value as a parameter. Hence, we define a function value in the next line. Then we pass the function value to the map method.
We have another alternative to do the same thing. Instead of defining function value and then passing it in the next line, we can do both of the things in a single line.
The next line is passing an inline function value to the map method. Did you notice the Scala type inference?
When we define a function value, we have to specify the type of x. However, when we pass that same value as an inline definition, we do not have to specify the type of x.
Do you understand, How Scala infers the type of x in the above example?
Scala knows that the r is a range of integers and hence the map method takes a function of type Int => Int.
However, why the hell are we using a parameter list?
Let's look at these two examples.


                                        
    r.map(x => x + 10)
    r.reduce((x,y) => x * y )                 
                                    

In case of map method, Scala already knows that the map method takes a function with the single input parameter. So why can't we remove x = > ? Why do I still need to code it?
Similarly, Scala already knows that the reduce method takes a function with two input parameters. So why can't we remove (x,y) => ?
Let's do it. The new code looks as shown below.

                                        
    r.map(x + 10)
    r.reduce(x * y )                
                                    

In the above code examples, Scala will complain as What is x? and What is y? Is it a free variable?
No. These are not free variables. The x and the y are the parameters.
That is where the placeholder value comes in. Scala allows us to replace the reference to the input parameters with an underscore and write the above code as below.

                                        
    r.map(_ + 10)
    r.reduce(_ * _ )                 
                                    

This syntax is known as the placeholder syntax. The placeholder syntax makes it possible to remove the list of parameters. We only supply the body and tell Scala that we want you to replace the underscores with actual parameters. It is similar to telling Scala to replace the first underscore with the first parameter value, second underscore with the second parameter value and so on. These underscores are a fill in the blanks for Scala. The compiler will fill in the input parameters in a sequence. The only point to remember is following.
The first underscore represents the first parameter. The second underscore represents the second parameter. The third underscore represents the third parameter and so on.
Hence, the number of parameters and the number of underscores must be same.
Scala will fill in parameters in a sequence. I have some examples below to clarify the main idea.


                                            
    //Can you write this example using a placeholder syntax?
    r.filter(x => x > 5)
    //Yes
    r.filter(_ > 5)
    //Can you do this one also?
    r.reduce((x,y) => x + y / x min y)
    //"No"                  
                                        

We cannot use placeholder syntax for the last example shown above. Because there are two parameters, but we are using them more than once. In that case, we need four underscores, but that violates the rule that the number of parameters and the number of underscores must be same.
You will see a frequent use of the placeholder syntax in the single line function literals. However, they are just a syntactic sugar to squeeze your code by removing the parameter list.

Read More

Basics of Scala functions | Function Literals in Scala | Function values | Local Functions | Variable length argument | Default values and named arguments | Scala Placeholder syntax | Higher Order functions | Partially applied functions | Function currying

By Prashant Pandey -


You will also like:


Pattern Matching

Scala takes the credit to bring pattern matching to the center.

Learning Journal

What is a closure?

A closure is a function. Like any other Scala function, a Closure may be pure or impure.

Learning Journal

Hadoop Security

Hadoop security implementation using Kerberos.

Learning Journal

Statements and Expressions

Statements and Expressions in Scala. How are they different?

Learning Journal

Lazy Evaluations

Evaluate the expression now vs evaluate it for the first use. Strict vs Lazy?

Learning Journal