9

Scala 是否有与 golangs defer 相同的功能?

来自: http: //golang.org/doc/effective_go.html#defer

Go 的 defer 语句安排一个函数调用(延迟函数)在执行 defer 的函数返回之前立即运行。这是一种不寻常但有效的方式来处理诸如无论函数采用哪条路径返回都必须释放资源的情况。典型示例是解锁互斥锁或关闭文件。

4

3 回答 3

9

Scala 并非defer按设计提供,但是您可以通过将函数包装在另一个函数中来自己创建它,并传递一个跟踪要调用的函数的对象。

例子:

class DeferTracker() {
  class LazyVal[A](val value:() => A)

  private var l = List[LazyVal[Any]]()
  def apply(f: => Any) = { l = new LazyVal(() => f) :: l }
  def makeCalls() = l.foreach { x => x.value() }
}

def Deferrable[A](context: DeferTracker => A) = {
  val dt = new DeferTracker()
  val res = context(dt)
  dt.makeCalls
  res
}

在此示例中,Deferable将是调用context并返回其内容的包装函数,为它提供一个跟踪defer调用的对象。

您可以像这样使用此构造:

def dtest(x:Int) = println("dtest: " + x)

def someFunction(x:Int):Int = Deferrable { defer =>
  defer(dtest(x))
  println("before return")
  defer(dtest(2*x))

  x * 3
}

println(someFunction(3))

输出将是:

before return
dtest: 6
dtest: 3
3

我知道这可以通过不同的方式解决,但这实际上只是 Scala 支持延迟概念的一个例子,没有太多大惊小怪。

于 2013-09-17T21:22:51.087 回答
5

我想不出 Scala 特定的方式,但这不是等效的(尽管不是那么漂亮):

try {
    // Do stuff   
} finally {
    // "defer"
}
于 2013-09-17T08:50:20.567 回答
2

不,Go 有这个结构正是因为它不支持异常并且没有try...finally语法。

就个人而言,我认为它会引发维护噩梦。对 defer 的调用可以隐藏在函数的任何地方。即使负责任的编码人员将延迟放在要清理的东西旁边,我认为它不如一个finally块那么清楚,至于它让凌乱的编码器做什么......至少finally块将所有清理工作放在一个地方。

defer与惯用的Scala相反。Scala 提供了控制程序流的一元方法,而defer魔法根本没有贡献。Monads 提供了一个功能改进try...finally,让你

  • 定义自己的错误处理流程
  • 功能性地操作定义的流程
  • 将函数的预期错误作为其签名的一部分

defer在这方面没有地位。

于 2013-09-17T08:59:10.620 回答