scala中双参数化函数的含义是什么?

时间:2016-08-14 17:10:44

标签: scala

我正在通过火花的测试代码。虽然我理解下面给出的函数背后的逻辑

它意味着什么,以下语法定义有什么好处?


测试代码

def withStreamingContext[R](ssc: StreamingContext)(block: StreamingContext => R): R = {
try {
  block(ssc)
} finally {
  try {
    ssc.stop(stopSparkContext = true)
  } catch {
    case e: Exception =>
       logError("Error stopping StreamingContext", e)
   }
  }
} 

为什么必须这样定义?为什么不能

def withStreamingContext[R](ssc: StreamingContext,block: StreamingContext => R): R = 

4 个答案:

答案 0 :(得分:3)

嗯,它可以。将参数分成两个或多个参数列表称为currying。这样,双参数函数可以转换为一个函数,该函数接受一个参数并返回一个接受一个参数并返回结果的函数。这就是您发布的代码中发生的情况。每个 n - 参数函数都可以看作 n 1参数函数(事实上,在Haskell中,所有函数都被这样处理)。

请注意,Scala还有一个部分应用函数的概念,归结为同样的事情。 PAF和currying都允许您只传递一个参数子集,从而接收一个剩余的函数。

例如,

def sum(x: Int, y: Int) = x + y

可以用咖喱,然后你可以说,例如:

def sum(x: Int)(y: Int) = x + y
def addTwo = sum(2) _ // type of addTwo is Int => Int

为您提供相同的功能,但应用了第一个参数。使用PAF,它将是

def sum(x: Int, y: Int) = x + y
def addTwo = sum(2, _: Int)

答案 1 :(得分:1)

使用起来更方便:

withStreamingContext(ssc) {
  doSomething()
  doSomethingElse()
}

VS

withStreamingContext(ssc, { doSomething(); doSomethingElse() })

答案 2 :(得分:1)

首先

def a(x: Int)(y: Int) = x * y

的语法糖
def a(x: Int) = (y: Int) => x * y

这意味着您定义了一个返回函数的方法(关闭x) 您可以在没有所有参数列表的情况下调用此方法并传递返回的函数。您也可以部分应用任何其他方法,但我认为这种语法更清晰。

此外,可以使用表达式语法调用具有一元参数列表的函数/方法。

withStreamingContext(ssc) {
  // your code block passed to function
}

答案 3 :(得分:1)

这种声明功能称为currying。它由MosesSchönfinkel独立介绍,后来由Haskell Curry从它的名字所在地引入。这个概念实际上源于数学,然后被引入计算机科学。

经常与部分功能应用混淆;主要区别在于对部分应用函数的调用会立即返回结果,而不是“currying”链中的另一个函数。

scala> def foo (x:Int, y:Int, z:Int) : Int = x + y + z
foo: (x: Int, y: Int, z: Int)Int

scala> val pa = foo(1, _:Int, _:Int)
pa: (Int, Int) => Int = <function2>

scala> pa(2,3)
res0: Int = 6

相反,给定f:(x,y,z) -> n,currying产生f':x -> (y -> (z -> n))。换句话说,将每个参数依次应用于上一次调用返回的单个参数函数。 在调用f'(1)之后,返回一个接受单个参数并返回另一个函数的函数,而不是一个带有两个参数的函数。 相比之下,部分函数应用程序指的是将多个参数固定到函数的过程,从而产生较小arity的另一个函数。这两者经常混为一谈。

已经提到了currying的好处/优点elsewhere。你遇到的主要问题是理解语法及其起源,已经解释过了。