Scala Thunk或代码块

时间:2017-10-24 09:30:00

标签: scala

我在SCALA GOTCHA: BLOCKS AND FUNCTIONSAlvin博客中了解了棘手的Scala代码块。这是Alvin的一个示例,他使用泛型函数f: A=> B代替() => A=> A代码块参数。

我更改了代码以返回Int而不是String,请参阅#1

case class Foo[A, B](f: A => B) {
    println(f)
    def print1 { println("1") }
    }

    object AnonymousClassTest1 extends App {

    val f1 = Foo {
        println("hello from the `f1` instance")
        // "this is the result of the block of code" // #1
        123
    }
        f1.print1
    }

此代码编译时出现错误

Example.scala:5: error: type mismatch;
 found   : Int(123)
 required: ? => ?
           123
           ^
one error found

鉴于 f 是一个通用函数,它接受任何东西并返回任何东西。为什么会出现编译错误?为什么它可以接受String而不是Int?感谢。

1 个答案:

答案 0 :(得分:3)

让我们将解释分为两部分: Scala允许替换参数列表,用块接受一个参数:

def foo(arg: Int) = arg + 42
foo(42) == foo { 42 }

因此,对于您的代码,以下内容应该是正确的

val f1 = Foo {
myGreatCode
}
val f2 = Foo(myGreateCode)
f1 == f2

值(表示类型)"返回"来自块是后者的最后一个表达式,所以在你的情况下:

val f1 = Foo {
    println("hello from the `f1` instance")
    // "this is the result of the block of code" // #1
    123
}
f1 == Foo(123) // println is executed before creating Foo

我希望它能解释为什么会出现编译错误。为了满足您的需求,scala提供了特殊的语法,允许在块中定义函数:

val f2 = Foo { x: String =>
  x.toInt
} // Foo[String, Int]

编辑:

在评论中讨论后,我找到了解释为什么Foo("123")编译的解释。如果有人检查代码,他/她将发现以下实例的通用参数是:Foo[Int, Char]。 这是因为以下原因:

  1. 编译器期望Foo.apply的参数是函数

  2. 传递的值不是函数,因此编译器会寻找隐式转换为函数。

  3. 它找到:implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else nullWrappedString扩展IndexedSeq[Char],后者又扩展Int => Char