Scala Tutorial - Learn How To Create Function With Option Return Type
Overview
In this tutorial, we will learn how to create and use function whose return type is an Option.
Feel free to review the tutorial from Chapter 2 on how to use Option, Some and None to help avoid the dreaded NullPointerException.
Steps
1. How to define a function which returns an Option of type String
Let's define a function named dailyCouponCode() which will assume a database lookup to provide our customers with a daily coupon code.
Since there may or may not be a daily coupon code available, it would be a good idea for the users of our dailyCouponCode() function to be aware explicitly of the possibility that the daily coupon code may be empty.
As such, you can define the dailyCouponCode() function's return type to be an Option of the type String.
println(s"Step 1: Define a function which returns an Option of type String")
def dailyCouponCode(): Option[String] = {
// look up in database if we will provide our customers with a coupon today
val couponFromDb = "COUPON_1234"
Option(couponFromDb).filter(_.nonEmpty)
}
NOTE:
- We are also lifting the couponFromDb value into an Option which will perform a null check.
- We then remove any empty strings using the filter() function.
2. How to call function with Option return type using getOrElse
Since the dailyCouponCode() function from Step 1 returns an Option of type String, you should use getOrElse() function when retrieving its return value.
println(s"\nStep 2: Call function with Option return type using getOrElse")
val todayCoupon: Option[String] = dailyCouponCode()
println(s"Today's coupon code = ${todayCoupon.getOrElse("No Coupon's Today")}")
You should see the following output when you run your Scala application in IntelliJ:
Step 2: Call function with Option return type using getOrElse
Today's coupon code = COUPON_1234
NOTE:
- When using getOrElse() function, you need to also provide a default value which in our case will be "No Coupon's Today".
3. How to call a function with Option return type using pattern matching
By now you should have seen pattern matching in the previous tutorials, otherwise feel free to review the tutorial on pattern matching. As such you can use pattern matching on the return value of a function with Option return type and provide the behaviours for the Some or None case.
println(s"\nStep 3: Call function with Option return type using pattern matching")
dailyCouponCode() match {
case Some(couponCode) => println(s"Today's coupon code = $couponCode")
case None => println(s"Sorry there is no coupon code today!")
}
You should see the following output when you run your Scala application in IntelliJ:
Step 3: Call function with Option return type using pattern matching
Today's coupon code = COUPON_1234
4. How to call function with Option return type using map() function
When using the getOrElse() function or pattern matching on a function which returns an Option, you will need to provide the default or None case.
However, if you only care about valid values from the Option, you can use the map() function.
println(s"\nStep 4: Call function with Option return type using map")
dailyCouponCode().map(couponCode => println(s"Today's coupon code = $couponCode"))
You should see the following output when you run your Scala application in IntelliJ:
Step 4: Call function with Option return type using map
Today's coupon code = COUPON_1234
5. Review function calculateDonutCost() function from previous tutorial
Let's review the calculateDonutCost() function from the previous tutorial Learn How To Use Option In Function Parameters which has an Option parameter for couponCode.
println("\nStep 5: Review function from previous tutorial which has an Option parameter")
def calculateDonutCost(donutName: String, quantity: Int, couponCode: Option[String]): Double = {
println(s"Calculating cost for $donutName, quantity = $quantity")
couponCode match {
case Some(coupon) =>
val discount = 0.1 // Let's simulate a 10% discount
val totalCost = 2.50 * quantity * (1 - discount)
totalCost
case None => 2.50 * quantity
}
}
Now you can pass it our dailyCouponCode() function from Step 1.
// apply daily coupon code if we have one
println(s"""Total cost with daily coupon code = ${calculateDonutCost("Glazed Donut", 5, dailyCouponCode())}""")
You should see the following output when you run your Scala application in IntelliJ:
Step 5: Review function from previous tutorial which has an Option parameter
Calculating cost for Glazed Donut, quantity = 5
Total cost with daily coupon code = 11.25
Summary
In this tutorial, we went over the following:
- How to define a function which returns an Option
- How to call a function which returns an Option using getOrElse
- How to call a function which returns an Option using Pattern Matching
- How to call a function which returns an Option using map() function
Tip
- How to use the fold function to extract the result from a function which returns an Option
println(s"\nTip - 1: Call function with Option return type using fold")
val todayCouponUsingFold: String = dailyCouponCode().fold("No Coupon Available")(couponCode => couponCode)
println(s"Today's coupon code = $todayCouponUsingFold")
- To learn more about uisng Option in general, follow the tutorial on Option, Some and None
Source Code
The source code is available on the allaboutscala GitHub repository.
What's Next
In the next tutorial, I will show you how to define function which takes implicit parameters.