最终可以用 Try 做吗?

St.*_*rio 4 scala exception

我是新手Scala并查看了源代码Try::apply

def apply[T](r: => T): Try[T] =
  try Success(r) catch {
    case NonFatal(e) => Failure(e)
  }
Run Code Online (Sandbox Code Playgroud)

它只是捕获非致命异常。但是如果我需要 finally 子句怎么办?是否可以以Try功能方式模拟它?我的意思是像

try{
   //acquire lock
   //do some
} finally {
  // release lock
}
Run Code Online (Sandbox Code Playgroud)

Try{
   //acquire lock
   //do some
} 
//Now how to release?
Run Code Online (Sandbox Code Playgroud)

fGo*_*fGo 5

这里已经回答类似的问题。

TLTR; Try monad 没有标准方法可以做到这一点。

通常的解决方法是这样的:

def use[A <: { def close(): Unit }, B](resource: A)(code: A ? B): B =
    try {
        code(resource)
    } finally {
        resource.close()
    }
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用:

val path = Paths get "/etc/myfile"
use(Files.newInputStream(path)) { inputStream ?
    val firstByte = inputStream.read()
    ....
}
Run Code Online (Sandbox Code Playgroud)

此处解释的另一种方法意味着您通过添加附加方法“withRelease”来“扩展”标准“Try”

implicit class TryOps[A <: { def close(): Unit }](res: Try[A]) {
  def withRelease() = res match {
    case Success(s) => res.close(); res
    case Failure(f) => res.close(); res
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,

Try {
   val inputStream = Files.newInputStream(path))
   ...
   inputStream
}.withRelease()
Run Code Online (Sandbox Code Playgroud)


Gab*_*lla 4

由于Try解析为一个值并且当出现故障时它不会展开堆栈,因此您可以简单地在Try执行后执行清理操作。例如:

val someLock = ??? // acquire some lock
val result = Try {
  // do something and return a result
}
someLock.release()
Run Code Online (Sandbox Code Playgroud)

如果您愿意,您可以推出自己的助手,将所有内容保存在一个表达式中:

def withLock[A](f: Lock => A): Try[A] = {
  val lock = ??? // acquire the lock
  val res = f(lock)
  lock.release()
}
Run Code Online (Sandbox Code Playgroud)

然后你可以写:

val res = withLock { lock =>
 // some operation
}
Run Code Online (Sandbox Code Playgroud)

这通常称为贷款模式