我目前正在进行关于函数式编程的演示,并且遇到了以下问题。斯卡拉的尝试是否透明?
函数式编程旨在将'what'与'how',或者更确切地说是从其解释中的计算声明中分离出来。这就是为什么这种范例的主要焦点之一是使用可组合的数据结构来表示计算,而不做任何关于它们如何执行的假设。例如:
// Represents a computation that may fail
case class Unsafe[A,B](run: A => B)
// ...
val readIntFromFile: Unsafe[String, Int] = Unsafe { filePath => /* ... */ }
interpret(readIntFromFile)
// Interpreter
def interpret(u: Unsafe[String, Int]): Unit = {
try {
u.run("path/to/file")
} catch {
case e => /* ... */
}
}
这似乎是有道理的,因为副作用应该计算的执行过程中,而不是其声明中只执行。问题是,在Scala中,因为它似乎,许多数据结构打破了这个规则:
object Try {
/** Constructs a `Try` using the by-name parameter. This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
*/
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
}
同为Futures
:
/** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
*
* The result becomes available once the asynchronous computation is completed.
*
* @tparam T the type of the result
* @param body the asynchronous computation
* @param executor the execution context on which the future is run
* @return the `Future` holding the result of the computation
*/
def apply[T](body: =>T)(implicit @deprecatedName('execctx) executor: ExecutionContext): Future[T] = impl.Future(body)
所以,我现在想知道,是Try
和Future
真透明的?如果不是,那么如何处理错误情况而不依赖于Success
和Failure
?
非常酷的答案。我从来没有想过像这样尝试。 –
我还会补充一点:我觉得大多数时候,'Try'是错误的抽象,而'Either'和'IO'更准确。 –
@FrancisToth我认为这或多或少是正确的。 '尝试'基本上就像声明“抛出异常”。这比根本不记录错误情况要好,但除此之外不会给你任何额外的信息,而且不像'Either'它要求你的错误情况是一个例外。另一方面,“IO/Task”处理完全不同的问题。 – puhlen