Scala Tutorial - Learn How To Create Higher Order Function - Call-By-Name Function

By Nadim Bahadoor | Last updated: July 25, 2017 at 13:50 pm

Overview

In this tutorial, we will learn how to create Higher Order Function which is a function that takes another function as its parameter.

 

This tutorial is a continuation of the previous Higher Order Function tutorial and we will showcase the difference between call-by-name and call-by-value function parameters.

Steps

1. How to define a List with Tuple3 elements

Let's start by defining a List containing Tuple3 elements which would represent the name of a donut, the quantity to be purchased and its price.

 

If you are unfamiliar with the Scala Tuple syntax, feel free to review the tutorial on Tuples.


println("Step 1: How to define a List with Tuple3 elements")
val listOrders = List(("Glazed Donut", 5, 2.50), ("Vanilla Donut", 10, 3.50))

 

2. How to define a function to loop through each Tuple3 elements of the List and calculate total cost

Assume that your donut store sells donuts worldwide and as such you need to convert the total cost of buying donuts to the local currency being used.

 

To this end, let's define a placeOrder() function which would take a list of donut orders as defined in Step 1. But the function also has an exchangeRate parameter to convert the total cost to the local currency.


println("\nStep 2: How to define a function to loop through each Tuple3 of the List and calculate total cost")
def placeOrder(orders: List[(String, Int, Double)])(exchangeRate: Double): Double = {
  var totalCost: Double = 0.0
  orders.foreach {order =>
    val costOfItem = order._2 * order._3 * exchangeRate
    println(s"Cost of ${order._2} ${order._1} = £$costOfItem")
    totalCost += costOfItem
  }
  totalCost
}

NOTE:

  • We could have inlined the totalCost calculation and avoid the use of var, but we are showing each step of the calculation.
  • We are also using parameter groups similar to what you've learned from the tutorial on Curried Function With Parameter Groups.

3. How to call function with curried group parameter for List of Tuple3 elements

The syntax for calling the placeOrder() function with currying parameters should be familiar to you already if you've followed the previous tutorials.


println("\nStep 3: How to call function with curried group parameter for List of Tuple3 elements")
println(s"Total cost of order = £${placeOrder(listOrders)(0.5)}")

You should see the following output when you run your Scala application in IntelliJ:


Step 3: How to call function with curried group parameter for List of Tuple3 elements
Cost of 5 Glazed Donut = £6.25
Cost of 10 Vanilla Donut = £17.5
Total cost of order = £23.75

NOTE:

  • For simplicity, we're using 0.5 as the exchange rate.

4. How to define a call-by-name function

You should have already seen the syntax for call-by-name function as per the previous tutorial on Higher Order Function.

 

As a result, let's redefine a placeOrder function which will accept a call-by-name parameter for the exchange rate.


println("\nStep 4: How to define a call-by-name function")
def placeOrderWithByNameParameter(orders: List[(String, Int, Double)])(exchangeRate: => Double): Double = {
  var totalCost: Double = 0.0
  orders.foreach {order =>
    val costOfItem = order._2 * order._3 * exchangeRate
    println(s"Cost of ${order._2} ${order._1} = £$costOfItem")
    totalCost += costOfItem
  }
  totalCost
}

NOTE:

  • The call-by-name function parameter exchangeRate: => Double will evaluate any exchangeRate function each time it is called.
  • This is in contrast to the function defined in Step 1 above which had a call-by-value function parameter for exchange rate. This meant that any exchange rate passed through would be evaluated only once.

5. How to define a simple USD to GBP function

With the call-by-name exchange rate parameter from Step 4 in mind, let's create a function which will randomly generate a USD to GBP currency conversion.


println("\nStep 5: How to define a simple USD to GBP function")
val randomExchangeRate = new Random(10)
def usdToGbp: Double = {
  val rate = randomExchangeRate.nextDouble()
  println(s"Fetching USD to GBP exchange rate = $rate")
  rate
}

6. How to call function with call-by-name parameter

We can then pass the USD to GBP function to the placeOrderWithByNameParameter() function as shown below.

 


println("\nStep 6: How to call function with call-by-name parameter")
println(s"Total cost of order = £${placeOrderWithByNameParameter(listOrders)(usdToGbp)}")

You should see the following output when you run your Scala application in IntelliJ:


Step 6: How to call function with call-by-name parameter
Fetching USD to GBP exchange rate = 0.7304302967434272
Cost of 5 Glazed Donut = £9.13037870929284
Fetching USD to GBP exchange rate = 0.2578027905957804
Cost of 10 Vanilla Donut = £9.023097670852312
Total cost of order = £18.15347638014515

NOTE:

  • For each order in the list, a new exchange rate is being created and that's because the call-by-name function usdToGbp function is being evaluated each time.

This concludes our tutorial on Learn How To Create Higher Order Function - Call-By-Name Function and I hope you've found it useful!

 

Stay in touch via Facebook and Twitter for upcoming tutorials!

 

Don't forget to like and share this page :)

Summary

In this tutorial, we went over the following:

  • How to define a List with Tuple3 elements
  • How to define a function to loop through each Tuple3 elements of the List and calculate total cost
  • How to call function with curried group parameter for List of Tuple3 elements
  • How to define a call-by-name function
  • How to define a simple USD to GBP function
  • How to call function with call-by-name parameter

Tip

Source Code

The source code is available on the allaboutscala GitHub repository.

 

What's Next

In the next tutorial, I will continue the discussion on Higher Order Function and call-by-name function but focus on function which accepts a callback function parameter.

Nadim Bahadoor on FacebookNadim Bahadoor on GithubNadim Bahadoor on LinkedinNadim Bahadoor on Twitter
Nadim Bahadoor
Senior Software Developer | Nephila Capital
Founder of allaboutscala.com. I have over 10 years of experience in building large scale real-time trading systems in the financial industry. Passionate about Distributed Systems, Scala, Big Data and Functional Programming. Stay in touch for upcoming tutorials!
Other allaboutscala.com tutorials you may like:

Share this article on