3

PDFライブラリを使用しているときにこれに遭遇しましたが、このような便利なものが他にもたくさんあります.

リソース (閉じる必要がある) があり、これらのリソースを使用して、リソースが開いていてまだ解放されていない場合にのみ有効なオブジェクトを取得する場合がよくあります

b以下のコードの参照は、 a が開いている間のみ有効であるとしましょう:

val a = open()
try {
  val b = a.someObject()
} finally {
  a.close()
}

さて、このコードは問題ありませんが、このコードはそうではありません:

val b = {
  val a = open()
  try {
    a.someObject()
  } finally {
    a.close()
  }
}

そのコードは、リソース a の何かへの参照があり、a はもう開いていません。

理想的には、次のようなものが必要です。

// Nothing producing an instance of A yet, but just capturing the way A needs
// to be opened.
a = Safe(open()) // Safe[A]

// Just building a function that opens a and extracts b, returning a Safe[B]
val b = a.map(_.someObject()) // Safe[B]

// Shouldn't compile since B is not safe to extract without being in the scope 
// of an open A.
b.extract 

// The c variable will hold something that is able to exist outside the scope of 
// an open A.
val c = b.map(_.toString)

// So this should compile
c.extract
4

1 に答える 1

2

あなたの例では、既に閉じられているストリームにアクセスすると例外がスローされるのが一般的です。util.Tryこの使用例のために正確に作成されたが存在します。

scala> import scala.util._
import scala.util._

scala> val s = Try(io.Source.fromFile("exists"))
s: scala.util.Try[scala.io.BufferedSource] = Success(non-empty iterator)

// returns a safe value
scala> s.map(_.getLines().toList)
res21: scala.util.Try[List[String]] = Success(List(hello))

scala> s.map(_.close())
res22: scala.util.Try[Unit] = Success(())

scala> val data = s.map(_.getLines().toList)
data: scala.util.Try[List[String]] = Failure(java.io.IOException: Stream Closed)

// not safe anymore, thus you won't get access to the data with map
scala> data.map(_.length)
res24: scala.util.Try[Int] = Failure(java.io.IOException: Stream Closed)

他のモナドと同様にTry、ラップされた値に直接アクセスしないことをコンパイル時に保証します。その値を操作するには、高階関数を作成する必要があります。

于 2013-10-16T10:18:11.183 に答える