Search code examples
scalatypesmismatch

Scala compiler reports type mismatch for closure


I have code below:

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

The error message is:

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

I don't understand it very well. What's the different between println("" + _) and (String) => Unit? and why println("a") has not been treated as (String) => Unit also but println(_) does?


Solution

  • Statement 1

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

    Above is a short form of function literal called placeholder syntax. It is expanded like:

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

    Statement 2

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

    case _ is a wild card pattern. You can not use _ again. If you want to use case clause, you should use variable matching:

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

    Statements 3 & 4

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

    Note that "" + _ in println("" + _), itself is an anonymous function. So println("" + _) is considered as an expression.

    Compiler treats both, println("" + _) and println("a") as an expression, not as function literal passed as parameter. So it tries to evaluate println("" + _) and println("a") first, then passes result (Unit) to greeting, hence compilation error.