考虑一个返回另一个函数的函数:
def prepareFunction(args: List[Any]): String => Unit = {
println(s"Slow processing of $args...")
val results = args.map(a => s"processed $a")
def doSomething(s: String): Unit = {
println(s"Do something quick with $s and $results")
}
doSomething
}
Run Code Online (Sandbox Code Playgroud)
这里的想法是:外部函数执行一些繁重的处理并返回一个内部函数,该函数使用在封闭范围中定义的变量:
val doSomethingWithArgs = prepareFunction(List("arg1", "arg2", 3))
//> Slow processing of List(arg1, arg2, 3)...
doSomethingWithArgs("abc")
//> Do something quick with abc and List(processed arg1, processed arg2, processed 3)
doSomethingWithArgs("cde")
//> Do something quick with cde and List(processed arg1, processed arg2, processed 3)
Run Code Online (Sandbox Code Playgroud)
请注意,外部函数仅评估一次.
使用多个参数列表和Scala的Currying语法,我们可以编写类似的东西:
def prepareCurried(args: List[Any])(s: String): Unit = {
println(s"Slow processing of $args")
val results = args.map(a => s"processed $a")
def doSomething(s: String): Unit = {
println(s"Do something quick with $s and $results")
}
doSomething(s)
}
Run Code Online (Sandbox Code Playgroud)
但每次都会评估"外部"函数:
val doSomethingWithOtherArgs = prepareCurried(List(4, 5, 6)) _
doSomethingWithOtherArgs("abc")
//> Slow processing of List(4, 5, 6)
//> Do something quick with abc and List(processed 4, processed 5, processed 6)
doSomethingWithOtherArgs("cde")
//> Slow processing of List(4, 5, 6)
//> Do something quick with cde and List(processed 4, processed 5, processed 6)
Run Code Online (Sandbox Code Playgroud)
我的问题是,我可以以某种方式强迫prepareCurried在下面的线上进行评估吗?
val doSomethingWithOtherArgs = prepareCurried(List(4, 5, 6)) _
Run Code Online (Sandbox Code Playgroud)
换句话说,当部分应用具有多个参数列表的函数时,是否可以获得与"定义评估"相同的效果?
Tra*_*own 10
在这种情况下,reify从Scala的反射API 中突破可以帮助您了解语法如何被消除:
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> showCode(reify(prepareCurried(List(4, 5, 6)) _).tree)
res0: String =
{
val eta$0$1 = List.apply(4, 5, 6);
((s) => $read.prepareCurried(eta$0$1)(s))
}
Run Code Online (Sandbox Code Playgroud)
如果没有,就没有办法获得这个preparedCurried(eta)部分s.当您考虑如何在JVM上表示具有多个参数列表的方法时,这是有意义的(即,所有参数列表都被粉碎在一起).正如上面的评论者所说,如果您希望能够将第二个函数的准备与其应用程序分开,则需要显式返回一个函数.
| 归档时间: |
|
| 查看次数: |
261 次 |
| 最近记录: |