为什么我能';在Scala中,是否只对第一个参数应用下划线?

为什么我能';在Scala中,是否只对第一个参数应用下划线?,scala,Scala,我不知道为什么模式d在下面的列表中不好。 为什么需要expicit类型声明 def adder1(m:Int,n:Int) = m + n val a = adder1(2,_) //OK val b = adder1(_,2) //OK def adder2(m:Int)(n:Int) = m + n val c = adder2(2)(_) //OK val d = adder2(_)(2) //NG:missing parameter type val e = add

我不知道为什么模式d在下面的列表中不好。 为什么需要expicit类型声明

def adder1(m:Int,n:Int) = m + n

val a = adder1(2,_) //OK
val b = adder1(_,2) //OK

def adder2(m:Int)(n:Int) = m + n

val c = adder2(2)(_)     //OK
val d = adder2(_)(2)     //NG:missing parameter type
val e = adder2(_:Int)(2) //OK
我只想知道模式d需要参数类型的原因。
非常欢迎展示引文语言规范。

所以我相信这来自于引文语言规范的概念

直观地说,分部函数应用程序会说“如果您修复函数的第一个参数,那么您将得到一个包含其余参数的函数”

Scala使用占位符实现可选的部分应用程序,例如
def add(x:Int,y:Int)={x+y};add(1,u:Int)
返回一个递增函数。Scala还支持多个参数列表,例如
def add(x:Int)(y:Int)={x+y};添加(1)\ uu

让我们看一下
adder2

从REP:

scala> def adder2(m:Int)(n:Int) = m + n
def adder2(m: Int)(n: Int): Int
让我们获取一个值来表示:

scala> val adder2Value = adder2
                ^
       error: missing argument list for method adder2
       Unapplied methods are only converted to functions when a function type is expected.
       You can make this conversion explicit by writing `adder2 _` or `adder2(_)(_)` instead of `adder2`.
好的,让我们试试:

val adder2Value = adder2 _
val adder2Value: Int => (Int => Int) = $Lambda$1382/0x0000000840703840@4b66a923
啊哈

在英语中:“一个函数,它接受一个
Int
并返回一个函数,该函数接受一个
Int
并返回一个
Int
。”

如何使用此签名绑定第二个参数?除非我们首先经历了外部功能,否则我们如何才能访问内部功能

据我所知,除非您明确定义第一个参数的类型,否则使用此签名是不可能的

(但是,
adder2()()
?)呢

这更易于管理,我们现在可以修复任一参数,并获得简化的分部函数:

scala> val adder2FirstArg = adder2Value (_:Int) (10)
val adder2FirstArg: Int => Int = $Lambda$1395/0x000000084070d040@47f5ddf4

scala> val adder2SecondArg = adder2Value (5) (_:Int)
val adder2SecondArg: Int => Int = $Lambda$1396/0x000000084070c840@21ed7ce
这到底是怎么回事

当您将一个参数绑定到一个值时,您已经显式表示了该类型(可能是推断的,但在本例中肯定是该类型,
Int
s)。这是糖,所以我们不需要写。但在引擎盖下,这些都是组合功能,它们的组合方式非常重要。为了能够匹配和简化函数签名,编译器要求我们以从外到内的方式提供这些信息。否则,我们需要给它一些帮助才能到达那里

编辑:


然而,我认为这个问题更像是一个Scala语言规范的谜题练习。从设计的角度来看,我想不出任何好的理由来实现一个curried函数,因为你不能对参数进行排序,这样最后的参数就是被推断出来的参数。

老实说,在scalafiddle中,scala 2.12没有一个“OK”编译:。在菊石壳(2.13和2.11)@jwvh Yea中相同。。。我懂了。。。sbt也会正常编译它。我正在寻找原因:)。斯卡斯蒂在这里的工作就像sbt和Idea。多蒂也显示了这个错误<代码>缺少参数类型:我无法推断参数的类型$4。了解您在答案中查找的内容会很有帮助。你想要语言规范中的引用吗?语言设计者的推理解释?一个经验法则,知道什么时候这通常是必要的?可供选择的解决方法?请注意,
adder2(@Int)
可能不是您所认为的。。。它仍然是一个包含两个(curried)参数的函数,您将该函数应用于
2
,这将提供一个部分应用的函数,相当于
2+\uu
val adder2Value2= adder2Value (_:Int) (_:Int)
val adder2Value2: (Int, Int) => Int = $Lambda$1394/0x000000084070d840@32f7d983
scala> val adder2FirstArg = adder2Value (_:Int) (10)
val adder2FirstArg: Int => Int = $Lambda$1395/0x000000084070d040@47f5ddf4

scala> val adder2SecondArg = adder2Value (5) (_:Int)
val adder2SecondArg: Int => Int = $Lambda$1396/0x000000084070c840@21ed7ce