Scala Tutorial - Learn How To Create Function With Implicit Parameters
Overview
In this tutorial, we will learn how to create and use function which has implicit parameters.
The use of implicit parameters is just one example of how dependency injection can be achieved in Scala. As a matter of fact, dependency injection is built-into the Scala language such that you do not have to import another third party library such as Google Guice.
Feel free to review the Scala Features tutorial where dependency injection is outlined as being a first class citizen of the Scala language.
Steps
1. How to define a function which has an implicit parameter
In line with the examples from the previous tutorial, let us define a function to calculate the total cost when buying donuts by taking into account that our customers can benefit from a discount. To this end, we will define the discount parameter as implicit as shown below:
println(s"Step 1: How to define a function with an implicit parameter")
def totalCost(donutType: String, quantity: Int)(implicit discount: Double): Double = {
println(s"Calculating the price for $quantity $donutType")
val totalCost = 2.50 * quantity * (1 - discount)
totalCost
}
NOTE:
- The implicit parameter discount of type Double is defined using the keyword implicit within parenthesis after your usual function parameters.
- This means that the totalCost() function will require an implicit value of type Double to be in scope as defined in Step 2 below.
2. How to define an implicit value
The totalCost() function you've defined in Step 1 expects an implicit value of type Double to be in scope whenever the totalCost() function is called.
Therefore, you will define an implicit value of type Double somewhere within your codebase. Defining an implicit value is similar to defining any other values using the val keyword, except that you prefix the val keyword with the implicit keyword as well.
println("\nStep 2: How to define an implicit value")
implicit val discount: Double = 0.1
println(s"All customer will receive a ${discount * 100}% discount")
3. How to call a function which has an implicit parameter
Calling the totalCost() function is similar to calling any other function, except that you will not have to provide the implicit discount parameter.
println("\nStep 3: How to call a function which has an implicit parameter")
println(s"""Total cost with discount of 5 Glazed Donuts = ${totalCost("Glazed Donut", 5)}""")
You should see the following output when you run your Scala application in IntelliJ:
Step 3: How to call a function which has an implicit parameter
Calculating the price for 5 Glazed Donut
Total cost with discount of 5 Glazed Donuts = 11.25
NOTE:
- You did not have to manually pass-through the discount value when calling the totalCost() function.
- The Scala compiler will look for an implicit value of type Double for the discount implicit parameter which you've defined in Step 2.
- If there are no implicit values in scope, you will get a compiler error.
4. How to define a function which takes multiple implicit parameters
Defining additional implicit parameters is similar to defining any other parameters and you simply needs to separate the parameters using a comma.
As an example, let us expand the totalCost() function to take an implicit parameter of type String which will represent our Donut Store name.
println("\nStep 4: How to define a function which takes multiple implicit parameters")
def totalCost2(donutType: String, quantity: Int)(implicit discount: Double, storeName: String): Double = {
println(s"[$storeName] Calculating the price for $quantity $donutType")
val totalCost = 2.50 * quantity * (1 - discount)
totalCost
}
5. How to call a function which takes multiple implicit parameters
As per Step 4 above, the totalCost() function now expects an additional implicit value of type String.
Therefore, you need to first define another implicit value of type String so that it is in scope before you can call the totalCost() function.
println("\nStep 5: How to call a function which takes multiple implicit parameters")
implicit val storeName: String = "Tasty Donut Store"
println(s"""Total cost with discount of 5 Glazed Donuts = ${totalCost2("Glazed Donut", 5)}""")
You should see the following output when you run your Scala application in IntelliJ:
Step 5: How to call a function which takes multiple implicit parameters
[Tasty Donut Store] Calculating the price for 5 Glazed Donut
Total cost with discount of 5 Glazed Donuts = 11.25
6. How to manually pass-through implicit parameters
In rare occasions, you may have to manually pass-through the implicit parameter values. This can be done by passing the implicit parameters through another pair of parenthesis as shown below.
println("\nStep 6: How to manually pass-through implicit parameters")
println(s"""Total cost with discount of 5 Glazed Donuts, manually passed-through = ${totalCost2("Glazed Donut", 5)(0.1, "Scala Donut Store")}""")
You should see the following output when you run your Scala application in IntelliJ:
Step 6: How to manually pass-through implicit parameters
[Scala Donut Store] Calculating the price for 5 Glazed Donut
Total cost with discount of 5 Glazed Donuts, manually passed-through = 11.25
Summary
In this tutorial, we went over the following:
- How to define a function which has an implicit parameter
- How to define an implicit value
- How to call a function which has an implicit parameter
- How to define a function which takes multiple implicit parameters
- How to call a function which takes multiple implicit parameters
- How to manually pass-through implicit parameters
Tip
- It is a good practice to encapsulate your implicit values into an Object or a Package Object.
Source Code
The source code is available on the allaboutscala GitHub repository.
What's Next
In the next tutorial, I will show you how define function which itself is implicit.