-1

I am following this tutorial and I see this code:

    println("\nStep 1: How to define a higher order function which takes another function as parameter")
    def totalCostWithDiscountFunctionParameter(donutType: String)(quantity: Int)(f: Double => Double): Double = {
        println(s"Calculating total cost for $quantity $donutType")
        val totalCost = 2.50 * quantity
        f(totalCost)
    }

    println("\nStep 2: How to define and pass a def function to a higher order function")
    def applyDiscount(totalCost: Double): Double = {
        val discount = 2 // assume you fetch discount from database
        totalCost - discount
    }
    println(s"Total cost of 5 Glazed Donuts with discount def function = ${totalCostWithDiscountFunctionParameter("Glazed Donut")(5)(applyDiscount(_))}")

    println("\nStep 3: How to define and pass a val function to a higher order function")
    val applyDiscountValueFunction = (totalCost: Double) => {
        val discount = 2 // assume you fetch discount from database
        totalCost - discount
    }
    println(s"Total cost of 5 Glazed Donuts with discount val function = ${totalCostWithDiscountFunctionParameter("Glazed Donut")(5)(applyDiscountValueFunction)}")

The author says:

The function has a by-name parameter which is expected to be a function that has a parameter of type Double and will also return a type of Double.

Is that true? What would be a by-value parameter here? Is the function lazily evaluated which makes it a by-name parameter? Is that true?

Why does the author use the wildcard when passing in applyDiscount but not when passing in applydiscountValueFunction? Both work without the wildcard operator.

Jwan622
  • 11,015
  • 21
  • 88
  • 181

1 Answers1

2

applyDiscount(_) transforms the method into a function, using placeholder syntax for anonymous functions.

This process can be automated by the compiler (using a technique called eta-expansion) whenever a function type is expected and a method is passed instead, which is exactly the case in the example.

(for a more thorough discussion, refer to this answer: Underscore usage when passing a function in Scala)

So you're right in saying that this

totalCostWithDiscountFunctionParameter("Glazed Donut")(5)(applyDiscount)

would work anyway, because the compiler will transform the applyDiscount to a function automatically.


As per the by-name parameter, what the author is calling by-name parameter (the parameter f) is really just a parameter of type Double => Double, so it seems he's using incorrect terminology.

A by-name parameter in Scala is expressed using => like this:

def someMethod(someParam: => Double): Double = // ...

In this example someParam is a by name parameter, meaning it won't be evaluated at call-site.

Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235