我试图理解多个参数子句的这种语言特征以及为什么要使用它。 例如,这两个函数之间的区别是什么?
class WTF {
def TwoParamClauses(x : Int)(y: Int) = x + y
def OneParamClause(x: Int, y : Int) = x + y
}
>> val underTest = new WTF
>> underTest.TwoParamClauses(1)(1) // result is '2'
>> underTest.OneParamClause(1,1) // result is '2'
Scala specification at point 4.6中有一些内容。看看这对你有意义。
注意:规范称这些'参数子句',但我认为有些人也可能称之为'参数列表'。
答案 0 :(得分:9)
以下是多个参数列表的三种实际用法,
帮助进行类型推断。这在使用高阶方法时特别有用。下面,A
的类型参数g2
是从第一个参数x
中推断出来的,因此第二个参数f
中的函数参数可以省略,
def g1[A](x: A, f: A => A) = f(x)
g1(2, x => x) // error: missing parameter type for argument x
def g2[A](x: A)(f: A => A) = f(x)
g2(2) {x => x} // type is inferred; also, a nice syntax
对于隐式参数。只有最后一个参数列表可以隐式标记,并且单个参数列表不能混合隐式和非隐式参数。下面g3
的定义需要两个参数列表,
// analogous to a context bound: g3[A : Ordering](x: A)
def g3[A](x: A)(implicit ev: Ordering[A]) {}
根据以前的参数设置默认值
def g4(x: Int, y: Int = 2*x) {} // error: not found value x
def g5(x: Int)(y: Int = 2*x) {} // OK
答案 1 :(得分:8)
TwoParamClause
涉及两个方法调用,而OneParamClause
只调用 function 方法一次。我认为你要找的术语是 currying 。在众多用例中,它可以帮助您将计算细分为小步骤。这answer可能会让你相信currying的用处。
答案 2 :(得分:6)
两个版本之间在类型推断方面存在差异。考虑
def f[A](a:A, aa:A) = null
f("x",1)
//Null = null
此处,A
类型绑定到Any
,这是String
和Int
的超级类型。但是:
def g[A](a:A)(aa:A) = null
g("x")(1)
error: type mismatch;
found : Int(1)
required: java.lang.String
g("x")(1)
^
如您所见,类型检查器仅考虑第一个参数列表,因此A
绑定到String
,因此第二个参数中Int
的{{1}}值list是类型错误。
答案 3 :(得分:4)
多个参数列表可以帮助进行scala类型推断以获取更多详细信息,请参阅:Making the most of Scala's (extremely limited) type inference
类型信息不会从左到右在参数列表中,只能从从左到右跨参数列表< / strong>即可。所以,即使Scala知道前两个参数的类型......信息也不会流向我们的匿名函数。
...
现在我们的二元函数在一个单独的参数列表中,来自之前参数列表的任何类型信息都用于填写我们函数的类型 ...因此我们不需要注释我们的lambda参数。
答案 4 :(得分:3)
在某些情况下,这种区别很重要:
多个参数列表允许您使用TwoParamClauses(2);这是类型Int =&gt;的自动生成函数。 Int为其参数增加了2。当然你也可以使用OneParamClause自己定义相同的东西,但它需要更多的击键
如果你有一个隐式参数的函数也有显式参数,隐式参数必须全部在他们自己的参数子句中(这可能看起来像一个任意的限制,但实际上是非常明智的)
除此之外,我认为,不同之处在于风格。