什么触发Try参数被评估

时间:2018-01-07 13:44:05

标签: scala pass-by-name

我正在修补Try,依此:

val files = Stream("a.txt", "b.txt", "c.txt")
files
    .map(s => Try(Source.fromFile(s)))
    .flatMap(t => t match {
      case Failure(x) =>
        Console.err.println(s"Failure: x.getMessage")
        Stream.Empty
      case Success(s) => Stream(s)
    })
  .flatMap(t => t.getLines.toStream)
  .foreach(println)

当它工作时,正如我希望/预期的那样,我感到一种不安的感觉,我无法确切地知道" Source.fromFile(s)"部分实际得到评估。 Try.apply方法的参数被记录为一个名字参数,所以显然必须强制评估它。

但是,在我看来,下一次操作将是" t匹配"部分,并且查看Try.apply创建的对象类型,如果没有创建对象,它可以工作,并且无法在没有对象的情况下创建它评估要应用的参数。在这种情况下,我认为这个论点在第一时间没有任何意义。

或者,对于案例类的行为,可能存在一些本质上懒惰的东西?或许我只是遗漏了一些明显的东西。

有人会介意为我澄清这个吗?

1 个答案:

答案 0 :(得分:1)

您缺少的部分是Try的参数必须是名称,以便可以捕获该计算引发的异常并将其作为Failure来实现。否则,在Try有机会捕获任何会破坏目的的事情之前,将评估该参数。您甚至可以查看Try.apply的源代码,这非常简单。它立即强迫它的论点:

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