4

据我了解,部分应用的函数是函数,我们可以在不传递所有/部分必需参数的情况下调用它们。

def add(x:Int, y:Int) = x + y
val paf = add(_ :Int, 3)
val paf1 = add(_ :Int, _ :Int)

在上面的示例中,paf1 指的是缺少所有参数的部分应用函数,我可以调用 is using:paf1(10,20)并且可以调用原始函数 usingadd(10,20)

我的问题是,创建一个缺少所有参数的部分应用函数有什么额外好处,因为调用语法几乎相同?只是将方法转换为一流的函数吗?

4

4 回答 4

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>

在这个例子中,这似乎没什么好处,但在许多情况下,有非显式约束表明需要一个函数(或更准确地说,是在别处显式指定的约束),允许您简单地给出一个(类型兼容的)方法名称需要功能的地方。

于 2013-06-20T01:14:53.140 回答
2

更新:问题是,为什么我想要一个 eta 扩展的方法?Scala 圣经中最棒的修辞策略之一是它们会引导您找到一个多页的示例。我在下面使用出埃及记的比喻是因为我刚刚和查尔顿赫斯顿一起看过《十诫》。我并不是假装这个答案比兰德尔的答案更能解释。

您可能需要一些代表较少的人来注意圣经出埃及记中的主要内容是:

http://www.artima.com/pins1ed/first-steps-in-scala.html#step6

args foreach println.

“第一步”中的前一步确实是,

args foreach (arg => println(arg))

但我猜如果类型推断之神是善良的,没有人会这样做。

从规范中的更改日志中:“现在将部分未应用的方法指定为 m _ 而不是以前的符号 &m。” 也就是说,在某个时刻,“函数 ptr”的概念变成了不提供 args 的部分函数。它是什么。更新:“比喻。”

于 2013-06-20T02:16:27.207 回答
2

方法功能之间是有区别的。

如果你看一下List.map例如的声明,它真的需要一个函数。但是 Scala 编译器足够聪明,可以同时接受方法和函数。

来自这里的报价

这个技巧......用于将方法强制转换为预期函数的东西,非常容易,甚至编译器也可以检测并执行它。事实上,这种自动强制有一个自己的名字——它叫做 Eta 扩展。

另一方面,看看Java 8;据我所知,那里并不容易。

于 2013-06-20T06:46:12.297 回答
1

我相信其他人可以为此综合一堆用例,但实际上这只是函数是值这一事实的结果。如果您不能将函数作为正常值传递,那就更奇怪了。

Scala 对这些东西的处理有点笨拙。部分应用通常与柯里化结合使用。我认为这是一个怪癖,您基本上可以使用 eta 扩展任何表达式_。您通过写作有效地做的事情(模 Scala 的语法怪癖围绕currying)add(_ : Int, _ : Int)是写作(x : Int) => (y : Int) => add(x, y)。我相信您可以想到后一种定义在程序中可能有用的实例。

于 2013-06-20T00:51:07.607 回答