使用 curried 函数和映射的评估顺序
Order of evaluation with curried function and map
我对柯里化函数何时被替换以及这对程序性能的影响有一些疑问。
具体来说,给出以下代码:
def curriedFun(f: Stuff => OtherStuff)(stuff: Stuff) = ...
def normalFun(stuff: Stuff): OtherStuff = ...
...
listOfListsOfStuff: List[Stuff] = ...
val otherStuff: List[OtherStuff] =
listOfListsOfStuff.map(curriedFun(normalFun))
我的疑问是块的最后一次调用,更具体地说 map
如何与 curried 函数交互。特别是:
- 柯里化替换只发生一次吗?也就是说,在性能方面,代码是否等效于此:
val substitutedFun = curriedFun(normalFun)
val otherStuff: List[OtherStuff] =
listOfListsOfStuff.map(substitutedFun)
- 还是对
otherStuff
列表的每个元素替换一次?
我的直觉告诉我应该相当于事先代入函数(第一个选项),但我实在无法理解为什么,也不知道在哪里看...
方法的参数在调用方法之前计算(除非参数是按名称)。所以 map
的参数是在调用 map
之前计算的。
所以在这种情况下,curriedFun(normalFun)
被计算一次给一个函数,然后这个函数被传递给map
。 map
然后将此函数应用于 listOfListsOfStuff
的每个元素。 map
的参数是由柯里化函数生成的这一事实与执行顺序无关。
就我个人而言,我发现 scala -print
通常对这类问题很有用。例如,创建以下 Main.scala
文件
// Main.scala
def foo(i: Int)(j: String): String = j
List("hello", "world").map(foo(42))
然后执行 scala -print Main.scala
输出类似
def foo(i: Int, j: String): String = j;
def $anonfun$new(j: String): String = anon.this.foo(42, j);
new collection.immutable.::("hello", new collection.immutable.::("world", scala.collection.immutable.Nil)).$asInstanceOf[List]().map({
((j: String) => anon.this.$anonfun$new(j))
});
在 map
执行之前,我们看到柯里化被解析为 $anonfun$new
函数一次。
我对柯里化函数何时被替换以及这对程序性能的影响有一些疑问。
具体来说,给出以下代码:
def curriedFun(f: Stuff => OtherStuff)(stuff: Stuff) = ...
def normalFun(stuff: Stuff): OtherStuff = ...
...
listOfListsOfStuff: List[Stuff] = ...
val otherStuff: List[OtherStuff] =
listOfListsOfStuff.map(curriedFun(normalFun))
我的疑问是块的最后一次调用,更具体地说 map
如何与 curried 函数交互。特别是:
- 柯里化替换只发生一次吗?也就是说,在性能方面,代码是否等效于此:
val substitutedFun = curriedFun(normalFun)
val otherStuff: List[OtherStuff] =
listOfListsOfStuff.map(substitutedFun)
- 还是对
otherStuff
列表的每个元素替换一次?
我的直觉告诉我应该相当于事先代入函数(第一个选项),但我实在无法理解为什么,也不知道在哪里看...
方法的参数在调用方法之前计算(除非参数是按名称)。所以 map
的参数是在调用 map
之前计算的。
所以在这种情况下,curriedFun(normalFun)
被计算一次给一个函数,然后这个函数被传递给map
。 map
然后将此函数应用于 listOfListsOfStuff
的每个元素。 map
的参数是由柯里化函数生成的这一事实与执行顺序无关。
就我个人而言,我发现 scala -print
通常对这类问题很有用。例如,创建以下 Main.scala
文件
// Main.scala
def foo(i: Int)(j: String): String = j
List("hello", "world").map(foo(42))
然后执行 scala -print Main.scala
输出类似
def foo(i: Int, j: String): String = j;
def $anonfun$new(j: String): String = anon.this.foo(42, j);
new collection.immutable.::("hello", new collection.immutable.::("world", scala.collection.immutable.Nil)).$asInstanceOf[List]().map({
((j: String) => anon.this.$anonfun$new(j))
});
在 map
执行之前,我们看到柯里化被解析为 $anonfun$new
函数一次。