【问题标题】:Passing function as block of code between curly braces在花括号之间将函数作为代码块传递
【发布时间】:2014-05-05 09:47:03
【问题描述】:

有几次我看到这样的 Scala 代码:

object Doer{
   def doStuff(op: => Unit) {
      op
   }
}

以这种方式调用:

Doer.doStuff{
      println("Done")
}

对我来说奇怪的是,一个函数是如何传递给另一个函数的,只是花括号之间的一段代码。甚至没有通常标记参数列表开始和结束的括号。

这个 Scala 语法/功能的名称是什么?在什么情况下我可以使用它?它记录在哪里?

【问题讨论】:

  • 我认为它只是一种语法糖。圆括号不在这里,因为如果函数只有一个参数,您可以省略圆括号。而花括号内的这段代码就是提供匿名函数的方式。
  • @Ashalynd 否。您可以致电 f(args)f {block},但不能省略标点符号,除非是中缀 x op y。该区块只是{ case x => } 的匿名乐趣。

标签: scala syntax


【解决方案1】:

这被称为 nullary 函数thunk,是 按名称调用评估 的示例:http://www.scala-lang.org/old/node/138

您几乎可以在任何有参数列表的地方使用空值。它们基本上只是零参数函数周围的语法糖,使它们看起来像普通值,并且在被引用时被调用。

所以

def doSomething(op: => Unit) {
  op
}
doSomething {
  println("Hello!")
}

完全一样:

def doSomething(op: () => Unit) {
  op()
}
doSomething(() => println("Hello!"))

对于 nullaries 要记住的一件事是,每次引用它们时都会调用它们,因此类似于:

def foo(op: => Int) = op + op
foo {
  println("foo")
  5
}

将打印两次“foo”。

编辑:为了扩展 Randall 的评论,空值函数与零参数函数的一大不同之处在于空值不是一等值。例如,您可以拥有List[() => Int],但不能拥有List[=> Int]。如果你有类似的东西:

def foo(i: => Int) = List(i)

你没有将空函数添加到列表中,只是它的返回值。

【讨论】:

  • 最好不要将 thunk 视为函数。您绝对不能像使用函数一样使用 thunk,因为您不能选择将其视为要存储或传递的 Function 值。您只能触发对实际参数表达式(任意数量)的评估。
  • 要澄清评论,您可以这样做:def f(op: =>Int) = op _def g(op: =>Int) = f(op),所以 g(8) 不会评估。换句话说:按名称调用的参数是一种无参数的方法类型,例如def x
  • @som-snytt:我也不认为这是考虑名称参数的好方法。我反对尝试将概念 A 理解为概念 B 的变体,因为它们之间实际上只是一个模糊的、偶然的相似性……
  • @RandallSchulz 实际上,这不是一个隐喻,而是规范在 3.3.1 中将 =>A 定义为每次引用时都会评估的 expr 的精确方式,与别名相同参数。 (对我来说,这让我不去想它是如何实现或编码的。)
  • 为什么这么难找到任何官方文档?!
猜你喜欢
  • 1970-01-01
  • 2010-12-13
  • 2017-04-07
  • 1970-01-01
  • 2018-10-12
  • 2011-04-07
  • 1970-01-01
  • 2019-09-20
相关资源
最近更新 更多