Scala 编译器报告闭包类型不匹配

Scala compiler reports type mismatch for closure

我有以下代码:

test("temp") {
    def greeting(func: (String) => Unit, name: String) {
        func(name)
    }

    // Success
    greeting(println(_), "Hello")
    greeting( { case _ => println("" + `_`) },  "Hello")

    // Failed
    greeting(println("" + _), "Hello")
    greeting(println("a"), "Hello")
}

错误信息是:

Error:(52, 29) type mismatch;
     found   : Unit
     required: String => Unit
        greeting(println("" + _), "Hello")

Error:(53, 29) type mismatch;
     found   : Unit
     required: String => Unit
        greeting(println("a"), "Hello")
                        ^

不是很懂。 println("" + _) 和 (String) => Unit 有什么区别?为什么 println("a") 还没有被视为 (String) => Unit 而 println(_) 呢?

语句 1

greeting(println(_), "Hello") // placeholder syntax

上面是函数字面量的缩写形式,叫做 placeholder syntax。它扩展为:

greeting(x => println(x), "Hello")

语句 2

greeting( { case _ => println("" + `_`) },  "Hello") // wildcard pattern

case _ 是通配符模式。您不能再次使用 _。如果你想使用case子句,你应该使用变量匹配:

greeting( { case x => println("" + x) },  "Hello")

语句 3 和 4

greeting(println("" + _), "Hello")
greeting(println("a"), "Hello")

注意println("" + _)中的"" + _本身就是一个匿名函数。所以 println("" + _) 被认为是一个表达式。

编译器将 println("" + _)println("a") 都视为表达式,而不是作为参数传递的函数文字。因此它首先尝试评估 println("" + _)println("a"),然后将结果 (Unit) 传递给 greeting,因此出现编译错误。