[英]Is Scala's Try referentially transparent?
我目前正在編寫關於功能編程的演示文稿,並遇到了以下問題。
功能編程旨在將“什么”與“如何”分開,或者更確切地說,將計算的聲明與其解釋分開。 這就是為什么這個范例的主要焦點之一是使用可組合數據結構來表示計算,而不對它們的執行方式做出任何假設。 例如:
// 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的目的不是控制副作用,而是處理可能的異常。
如果您需要以純粹的方式控制副作用,您可以使用Cats和Scalaz等庫中的任務或IO類型。
Future
絕對不是RT,因為這兩個塊不等同:
這兩個期貨並行執行:
val fa: Future[Int] = service.call val fb: Future[Int] = service.call for { a <- fa; b <- fb } yield a + b
這兩個期貨按順序執行:
for { a <- service.call; b <- service.call } yield a + b
另一方面, Try
是。 處理錯誤的正確功能方法是使用Either[ErrorDescription, A]
作為返回A
但可能失敗的方法(您可以使用type ErrorDescription = Throwable
等效於scala.util.Try
!)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.