根据我的理解,部分应用的函数是函数,我们可以在没有函数的情况下调用它们 传递所有/一些必需的参数。
def add(x:Int, y:Int) = x + y
val paf = add(_ :Int, 3)
val paf1 = add(_ :Int, _ :Int)
在上面的例子中,paf1引用部分应用的函数,缺少所有参数,我可以调用使用:paf1(10,20)
并且可以使用add(10,20)
我的问题是,创建一个缺少所有参数的部分应用函数的额外好处是什么,因为调用语法几乎相同?它只是将方法转换为一级函数吗?
答案 0 :(得分:6)
Scala的def
关键字是您定义方法的方式,而方法不是函数(在Scala中)。所以你的add
不像你的paf1
那样是一流的函数实体,即使它们在生成结果时与它们的参数在语义上是等价的。
Scala会自动使用部分应用程序将方法转换为等效函数,您可以通过扩展示例来看到:
def add(x: Int, y: Int) = x + y
...
val pa2: (Int, Int) => Int = add
pa2: (Int, Int) => Int = <function2>
在这个例子中,这似乎没有什么好处,但是在很多情况下,存在非显式约束,表明需要一个函数(或更准确地说,在其他地方明确指定的约束),这些约束允许您简单地给出一个(类型兼容的)在需要函数的地方使用方法名称。
答案 1 :(得分:2)
更新:问题是,为什么我想要一个eta扩展方法? Scala圣经中最伟大的修辞策略之一是它们引导你在很多页面上得到一个例子。我使用下面的出埃及记比喻,因为我刚看到查理顿赫斯顿的“十诫”。我不是假装这个答案比兰德尔的解释更具说明性。
你可能需要一个代理人较少的人注意到圣经出埃及记中的大量积累是:
http://www.artima.com/pins1ed/first-steps-in-scala.html#step6
args foreach println
。
“第一步”中的上一步确实是
args foreach (arg => println(arg))
但是我猜测如果类型推断上帝是善良的话,没有人这样做。
从规范中的更改日志:“现在将部分未应用的方法指定为m _而不是 之前的符号&amp; m。“也就是说,在某个时刻,”函数ptr“的概念变成了一个没有提供args的部分函数。这就是它。更新:”比喻。“
答案 2 :(得分:2)
Methods 和 functions 之间存在差异。
例如,如果你看一下List.map
的声明,它确实需要一个函数。但是Scala编译器非常聪明,可以接受这两种方法和函数。
来自here
的引用这个技巧......用于将方法强制转换为需要函数的东西,即使编译器也可以检测并执行它。事实上,这种自动强制有一个自己的名字 - 它被称为Eta扩展。
另一方面,看看Java 8;据我所知,那里并不容易。
答案 3 :(得分:1)
我确信其他人可以为此合成一堆用例,但实际上这只是函数是值的结果。如果你不能将函数作为正常值传递,那将更加怪异。
Scala对这些东西的处理有点笨拙。部分应用通常与currying结合使用。我认为你可以使用_
基本上扩展任何表达式,这是一个怪癖。通过编写add(_ : Int, _ : Int)
,你有效地做了什么(模仿Scala关于currying的语法怪癖)正在编写(x : Int) => (y : Int) => add(x, y)
。我相信你可以想到后一个定义在程序中可能有用的实例。