为什么我能';在Scala中,是否只对第一个参数应用下划线?
我不知道为什么模式d在下面的列表中不好。 为什么需要expicit类型声明为什么我能';在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
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