什么';scala代码中发生了什么?回调函数

什么';scala代码中发生了什么?回调函数,scala,apache-spark,Scala,Apache Spark,取自Apache Spark,Dataset.scala() 第2132行: /** * Returns the number of rows in the [[Dataset]]. * @group action * @since 1.6.0 */ def count(): Long = withCallback("count", groupBy().count()) { df => df.collect(needCallback = false).head.getL

取自Apache Spark,Dataset.scala()

第2132行:

/**
  * Returns the number of rows in the [[Dataset]].
  * @group action
  * @since 1.6.0
  */
def count(): Long = withCallback("count", groupBy().count()) { df =>
  df.collect(needCallback = false).head.getLong(0)
}
第2393行:

/**
  * Wrap a Dataset action to track the QueryExecution and time cost, then report to the
  * user-registered callback functions.
  */
private def withCallback[U](name: String, df: DataFrame)(action: DataFrame => U) = {
  try {
      df.queryExecution.executedPlan.foreach { plan => plan.resetMetrics()
    }
    val start = System.nanoTime()
    val result = action(df)
    val end = System.nanoTime()
    sqlContext.listenerManager.onSuccess(name, df.queryExecution, end - start)
    result
  } catch {
  case e: Exception =>
    sqlContext.listenerManager.onFailure(name, df.queryExecution, e)
    throw e
  }
}
这是怎么回事?我不明白count()如何既等于withCallback,又有一个body;不知怎的,它是在withCallback返回的数据帧上被调用的,但我不理解语法。

方法
count()
实际上没有自己的主体。
count()
的主体实际上是一个函数文本,它定义了
withCallback
的“action”参数
count()
严格地说,它本身就是对带有回调(name,df)(action)的方法
的调用。(方法在Scala中可以有多个参数列表。)
withCallback
的值是
result
,这是
操作
函数计算结果的值

然而,你所经历的“困惑”是故意的。这个习惯用法——一个具有类型为函数或按名称值的终端参数列表的方法——允许定义语法上类似于语言扩展的内容。我们习惯于有特殊语法的语言,比如

try {
  // your code here
}
在Scala中,您可以编写自己的函数,如

// don't ask me why you would want to do this
def unreliably[T]( operation : =>T ) : Option[T] = {
   if (scala.math.random < 0.1) Some(operation) else None
}
它看起来就像新的语言语法!为了使它更像您的激励示例,我们可以修改定义,使其必须包含参数列表

// don't ask me why you would want to do this
def unreliably[T]( probability : Double )( operation : =>T ) : Option[T] = {
   if (scala.math.random < probability) Some(operation) else None
}
…而且您的代码有90%的几率被执行。代码定义了一个表达式,而不仅仅是一些无值语句,因此您还可以编写

val result = unreliably( probability = 0.9 ) {
   "great day"
}
result
的类型为
Option[String]
,因此您可以使用

println(s"""It's a ${result.getOrElse("terrible day")}.""")
现在,通过你自己的小“语言扩展”(这真的只是调用函数的一种有趣方式),你有了一个很好的小程序,它能让你十之八九都感到快乐

count()
方法实际上没有自己的主体。
count()
的主体实际上是一个函数文本,它定义了
withCallback
的“action”参数
count()
严格地说,它本身就是对带有回调(name,df)(action)的方法
的调用。(方法在Scala中可以有多个参数列表。)
withCallback
的值是
result
,这是
操作
函数计算结果的值

然而,你所经历的“困惑”是故意的。这个习惯用法——一个具有类型为函数或按名称值的终端参数列表的方法——允许定义语法上类似于语言扩展的内容。我们习惯于有特殊语法的语言,比如

try {
  // your code here
}
在Scala中,您可以编写自己的函数,如

// don't ask me why you would want to do this
def unreliably[T]( operation : =>T ) : Option[T] = {
   if (scala.math.random < 0.1) Some(operation) else None
}
它看起来就像新的语言语法!为了使它更像您的激励示例,我们可以修改定义,使其必须包含参数列表

// don't ask me why you would want to do this
def unreliably[T]( probability : Double )( operation : =>T ) : Option[T] = {
   if (scala.math.random < probability) Some(operation) else None
}
…而且您的代码有90%的几率被执行。代码定义了一个表达式,而不仅仅是一些无值语句,因此您还可以编写

val result = unreliably( probability = 0.9 ) {
   "great day"
}
result
的类型为
Option[String]
,因此您可以使用

println(s"""It's a ${result.getOrElse("terrible day")}.""")

现在,通过你自己的小“语言扩展”(这真的只是调用函数的一种有趣方式),你有了一个很好的小程序,它能让你十之八九都感到快乐

这是这是@luigi plinge谢谢你编辑我的尴尬@路易吉·普林奇感谢你为我排忧解难!