We learned about functions and function literals. There are few more concepts associated with the functions and function literals. In this video, I will talk about following items.
- Placeholder syntax
- Function values
- Local Functions
Scala Placeholder syntax
Let's start with the placeholder syntax. We have seen the below example earlier.
Let me show you another one.
The reduce method is another Higher Order function on Scala collections. Do you understand how
the reduce works? The reduce
method takes a binary operator function as input. Then it applies the function to the
collection.
That is why, in this example, we are passing a function literal that takes two input
parameters.
Like a map method, the reduce method is also a looping construct. In the first iteration, the
first
element goes as x and the second item replaces y. It collects the output. In this example, it
would
be x+y.
In the next iteration, the output from the previous iteration goes as x and the third
element
moves as y. This process repeats till the end, and we get the sum of the entire range as a
result.
We used simple sum, but you can use different algorithms in this loop to get a different
type
of information from the collection. Here are some examples.
We are not using type annotation for x and y. I covered it in the earlier video, so you already know the reason. Right? We don't use a type annotation because Scala already knows the type. But why the hell are we using the parameter list? I mean, Scala already knows that the reduce method takes a function with two arguments. Why can't we remove the argument list from there? Why do I still need to code it? That's where the placeholder syntax is useful. Let's me explain.
Look at the above method calls. What are we passing there? We are giving a function literal. It
contains two parts. A list
of parameters and the body. In the first case (the map method), Scala knows that you will pass
a
function that takes a single parameter. That restriction is imposed by the definition of the
map
method.
In the second case (the reduce method), Scala knows that you will pass a function that
takes
two input parameters. Again, that restriction is imposed by the definition of the reduce
method.
Right?
So, the list of arguments becomes optional. We can leave it because Scala already knows it.
Let
us remove that part.
Now, the Scala compiler will complain. What is x? and What is y? is it a free variable? No, Right? Those are parameters. So, we need to replace the reference to x with an underscore and write it like below.
The above syntax is known as the placeholder syntax.The placeholder syntax makes it possible to
remove the list of function
arguments. We only give the body and tell Scala that we want to use the parameter at the place
of
the underscore. That's it. Scala already knows everything else.
Similarly, in secondexample, we have two arguments, and we know that we need the first
argumentbefore
the *, and the second parameter after the *. So, Scala allows you to write it like this.
These underscores are a
fill in the blanks for Scala. The compiler will fill in first parameter to the first
place
and the second parameter to the second place. The only point to remember is this.
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. Right? Scala will fill in parameters in a sequence.
Now, a simple quiz. Can you write below example using a placeholder syntax?
Here is the answer.
Can you do this one also?
The answer is
"No" There are two parameters, but we are using them more than once. In this case, we
need
four underscores, but that violates the rule that the number of parameters and the number of
underscores
must match.
Great! The placeholder syntax is frequently used for a single line and simple function
literals.
You will often see that in your Scala journey. Just remember that the placeholder syntax allows
you
to remove the first part of the function literal and replace the parameter instances with an
underscore.
Scala Function value
There is another confusing term. The function values. A beginner is often confused with a function literal and a function value. We already learned about function literals. The following code represents a function literal. Right?
Do you know what happens internally? When you compile the above code, Scala will generate a class for that literal. The compiler will instantiate the class as an object and assign it to the value f. The generated code looks like below.
Typically, we use the function literal in two possible ways.
- Assign it to a value as we do in the above example.
- Pass it to a higher-order function or return it from a higher-order function.
In both cases, Scala compiler will generate a class for the function literal, instantiate the
class as an object and assign
it to a value. So, the function value is an object whereas a function literal is a source code
for
it. The literal is like a class, and the value is an object.
In the above example,
f is a function value whereas the code there is a function literal. That's it.
Local Functions in Scala
The next one is the local function, and it should be the simplest idea among all others that we learned so far. When we use an Object-Oriented approach, it is quite common to create private methods. They are a kind of helper methods, and we make them private because we don't want them to expose to the external world. Scala offers the same notion using the local functions. You can define functions inside other functions. They are visible only in their enclosing block. Here is an example.
The
getErrors function takes a file name as input, and it returns the error messages. We
are
using
isError as a local function. Simple as that. Sometimes, people also refer them as
Nested Function. The choice is yours, call them Nested or Local, but they are the same
thing.
Thank you very much.