Scala中函数定义中的多个参数子句有什么意义?

Nic*_*ler 9 functional-programming scala currying

我试图理解多个参数子句的这种语言特性以及为什么要使用它.例如,这两个功能之间的区别是什么?

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' 
Run Code Online (Sandbox Code Playgroud)

在第4.6点Scala规范中有一些内容.看看这对你有意义.

注意:规范称这些'参数子句',但我认为有些人也可能称之为'参数列表'.

Kip*_*ros 9

以下是多个参数列表的三种实际用法,

  1. 帮助类型推断.这在使用高阶方法时特别有用.下面,类型参数Ag2从第一参数推断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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 对于隐含参数.只有最后一个参数列表可以隐式标记,并且单个参数列表不能混合隐式和非隐式参数.以下定义g3需要两个参数列表,

    // analogous to a context bound: g3[A : Ordering](x: A)
    def g3[A](x: A)(implicit ev: Ordering[A]) {}
    
    Run Code Online (Sandbox Code Playgroud)
  3. 要根据以前的参数设置默认值,

    def g4(x: Int, y: Int = 2*x) {} // error: not found value x
    def g5(x: Int)(y: Int = 2*x) {} // OK
    
    Run Code Online (Sandbox Code Playgroud)


Jam*_*mil 8

TwoParamClause涉及两个方法调用,而只OneParamClause调用一次函数方法.我认为你正在寻找的术语是currying.在众多用例中,它可以帮助您将计算细分为小步骤.这个答案可能会让你相信currying的用处.


Lan*_*dei 6

两个版本之间在类型推断方面存在差异.考虑

def f[A](a:A, aa:A) = null
f("x",1)
//Null = null
Run Code Online (Sandbox Code Playgroud)

这里,类型A被绑定Any,这是一个超类型StringInt.但:

def g[A](a:A)(aa:A) = null
g("x")(1)

error: type mismatch;
 found   : Int(1)
 required: java.lang.String
       g("x")(1)
              ^
Run Code Online (Sandbox Code Playgroud)

正如你看到的,类型检查只考虑第一个参数列表,以便A获取绑定到String,所以Int对于价值aa在第二个参数列表是一个类型的错误.