这是一个名字功能参数吗?为什么通配符是可选的?

时间:2018-06-01 14:15:11

标签: scala

我正在关注this教程,我看到了这段代码:

    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)}")

作者说:

  

该函数有一个by-name参数,该参数应该是一个具有Double类型参数的函数,并且还将返回一个Double类型。

这是真的吗?这里的按值参数是什么?该函数是否被懒惰地评估,使其成为一个名字参数?这是真的吗?

为什么作者在传递applyDiscount时使用通配符,而不是在传入applydiscountValueFunction时?两者都没有通配符操作符。

1 个答案:

答案 0 :(得分:2)

applyDiscount(_)使用占位符语法将匿名函数转换为函数。

只要期望函数类型并且传递方法,编译器(使用称为 eta-expansion 的技术)就可以自动执行此过程,这与示例中的情况完全相同。 / p>

(有关更全面的讨论,请参阅此答案:Underscore usage when passing a function in Scala

所以你说这个

是对的
totalCostWithDiscountFunctionParameter("Glazed Donut")(5)(applyDiscount)

无论如何都会工作,因为编译器会自动将applyDiscount转换为函数。

根据by-name参数,作者调用的by-name参数(参数f)实际上只是Double => Double类型的参数,所以看来他&#39 ; s使用不正确的术语。

Scala中的by-name参数使用=>表达,如下所示:

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

在此示例中,someParam是一个名称参数,这意味着它不会在呼叫站点进行评估。