我不知道为什么模式 d 在下面的列表中不好。为什么需要显式类型声明?
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
Run Code Online (Sandbox Code Playgroud)
我只想知道模式 d 需要参数类型的原因。非常欢迎仅显示引文语言规范。
所以我相信这来自Partial Application的概念。
直观地说,偏函数应用程序说“如果你修复函数的第一个参数,你就会得到剩余参数的函数”
...
Scala 使用占位符实现可选的部分应用,例如
def add(x: Int, y: Int) = {x+y}; add(1, _: Int)返回一个递增函数。Scala 还支持多个参数列表作为柯里化,例如def add(x: Int)(y: Int) = {x+y}; add(1) _。
让我们看一下adder2
来自 REPL:
scala> def adder2(m:Int)(n:Int) = m + n
def adder2(m: Int)(n: Int): Int
Run Code Online (Sandbox Code Playgroud)
让我们获取一个值来表示这一点:
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`.
Run Code Online (Sandbox Code Playgroud)
好的,让我们尝试一下:
val adder2Value = adder2 _
val adder2Value: Int => (Int => Int) = $Lambda$1382/0x0000000840703840@4b66a923
Run Code Online (Sandbox Code Playgroud)
啊哈!
用英语:“一个接受 anInt并返回一个函数,一个接受 anInt并返回一个Int”
我们如何使用这个签名绑定第二个参数?除非我们首先访问外部函数,否则我们如何访问内部函数?
据我所知,除非您明确定义第一个参数的类型,否则不可能使用此签名来做到这一点。
(但是关于adder2(_)(_)?)
scala> adder2(_)(_)
^
error: missing parameter type for expanded function ((<x$1: error>, x$2) => adder2(x$1)(x$2))
^
error: missing parameter type for expanded function ((<x$1: error>, <x$2: error>) => adder2(x$1)(x$2))
Run Code Online (Sandbox Code Playgroud)
(也许这暗示了我们的解决方案?)
请注意,如果我们显式定义两个参数会发生什么:
val adder2Value2= adder2Value (_:Int) (_:Int)
val adder2Value2: (Int, Int) => Int = $Lambda$1394/0x000000084070d840@32f7d983
Run Code Online (Sandbox Code Playgroud)
这更易于管理,我们现在可以修复任一参数,并获得简化的部分函数:
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
Run Code Online (Sandbox Code Playgroud)
那么这里到底发生了什么?
当您将参数绑定到值时,您已经显式表达了类型(也许是推断出来的,但它肯定是该类型,在本例中为Ints)。它是糖,所以我们不需要写它。但在底层,这些是组合函数,它们的组合方式非常重要。为了能够匹配和简化函数签名,编译器要求我们以由外向内的方式提供此信息。否则,我们需要给它一些帮助才能到达那里。
编辑:
我认为这个问题更像是 Scala 语言规范。然而,拼图练习。从设计角度来看,我想不出任何好的理由,您需要以这样的方式实现柯里化函数,即您无法对参数进行排序,使得最后一个参数是被推断的参数。
| 归档时间: |
|
| 查看次数: |
276 次 |
| 最近记录: |