我是Scala的新手.我刚刚听到"eta扩展"一词,并且大致知道它意味着将方法扩展为函数对象.但我发现很少有资源可以系统地介绍它.
我很好奇eta扩展在Scala中是如何工作的.需要进行eta扩展的场景是什么?以及如何在Scala中实现eta扩展?
我大致知道在这种情况下:
def someMethod(x: Int): Int = x * x
Run Code Online (Sandbox Code Playgroud)
someMethod _ 将大致翻译成一个新的函数对象,如下所示:
new Function1[Int, Int] {
def apply(x: Int): Int = x * x
}
Run Code Online (Sandbox Code Playgroud)
是Scala的全部吗?
鉴于:
def save(f: => Any)(run:Boolean) { if (run) { println("running f"); f } else println("not running f") }
Run Code Online (Sandbox Code Playgroud)
我可以用它来调用它:
save("test")(true) -> running f
save("test")(false) -> not running f
save(throw new RuntimeException("boom!"))(false) -> not running f
save(throw new RuntimeException("boom!"))(true) -> running f and then exception thrown
Run Code Online (Sandbox Code Playgroud)
这是部分应用的奇怪行为:
save(throw new RuntimeException("boom!"))(_) -> (Boolean) => Unit = <function1> //as expected
save(throw new RuntimeException("boom!")) _ -> exception thrown
Run Code Online (Sandbox Code Playgroud)
立即评估代码块而不作为函数传递.上述两个陈述有什么区别?
起初我曾相信使用下划线来制作闭包(例如println _)只是使用箭头的简写(例如x => println x),但我最近才知道你也可以做以下事情:
def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce(f _)
Run Code Online (Sandbox Code Playgroud)
鉴于我过去的假设,f _看起来像一个闭包,它只接受一个参数并且只传递一个参数f.我以为它会告诉我它无法编译因为f需要两个参数,并且reduce应该期望一个带有两个参数的函数.但是就像我写的那样:
def f(a: Int, b: Int) = a + 2 * b
List(1, 2, 3).reduce((x, y) => f(x, y))
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?使用下划线创建闭包的规则是什么?
我有一个字符串数组:
val str:Array[String] = Array("aa","bb")
scala> str.foreach(println) // works
aa
bb
scala> str.foreach(println()) // println() also returns a Unit, doesn't it?
^
error: type mismatch;
found : Unit
required: String => ?
Run Code Online (Sandbox Code Playgroud)
为什么str.foreach(println)没有问题,但没有问题str.foreach(println())?
不println等于println()哪个返回Unit值?