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.
- Value declaration
- 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.
we define a function value in the next line. Then we pass the function value to the
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
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 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
actual parameters. It is similar to telling Scala to replace the first underscore
the first parameter value, second underscore with the second parameter value and so
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
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.
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