【问题标题】:Scala compiler reports type mismatch for closureScala 编译器报告闭包类型不匹配
【发布时间】:2016-05-05 16:30:58
【问题描述】:

我的代码如下:

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(_) 呢?

【问题讨论】:

    标签: scala types mismatch


    【解决方案1】:

    声明 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,因此编译错误。

    【讨论】:

    • 谢谢 Sudhir,这是否意味着编译器将函数调用优先级高于占位符语法?
    • 请看我更新的答案,它可能会消除你的疑问。
    • 编译器如何区分函数调用?因为 println("" + ) 里面也有 "" 。为什么它不是占位符语法?
    • 尝试在REPL中运行println("" + _),你会得到答案。
    • 总而言之,我可以认为当编译器遇到下划线时,它会一直认为它的所有者是一个闭包?这样它就不会立即被调用?因为下划线是一个可以即时填充的地方?此外,下划线的有效范围仅限于 {"" + _},因此函数 println 不被认为是匿名函数。我说的对吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多