我在SCALA GOTCHA: BLOCKS AND FUNCTIONS和Alvin博客中了解了棘手的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?感谢。
答案 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]
。
这是因为以下原因:
编译器期望Foo.apply的参数是函数
传递的值不是函数,因此编译器会寻找隐式转换为函数。
它找到:implicit def wrapString(s: String): WrappedString = if (s ne null) new WrappedString(s) else null
和WrappedString
扩展IndexedSeq[Char]
,后者又扩展Int => Char