Scala 中的贷款人模式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20762240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 05:57:45  来源:igfitidea点击:

Loaner Pattern in Scala

scala

提问by Kevin Meredith

Scala in Depthdemonstrates the Loaner Pattern:

Scala 深入演示了贷款人模式

def readFile[T](f: File)(handler: FileInputStream => T): T = {
  val resource = new java.io.FileInputStream(f)
  try {
    handler(resource)
  } finally {
      resource.close()
  }
}

Example usage:

用法示例:

readFile(new java.io.File("test.txt")) { input =>
   println(input.readByte)
}

This code appears simple and clear. What is an "anti-pattern" of the Loaner pattern in Scala so that I know how to avoid it?

这段代码看起来简单明了。Scala 中 Loaner 模式的“反模式”是什么,以便我知道如何避免它?

回答by Rex Kerr

Make sure that whatever you compute is evaluated eagerly and no longer depends on the resource. Scala makes lazy computation fairly easy. For instance, if you wrap scala.io.Source.fromFilein this way, you might try

确保你计算的任何东西都被急切地评估,不再依赖于资源。Scala 使惰性计算变得相当容易。例如,如果您scala.io.Source.fromFile以这种方式包装,您可以尝试

readFile("test.txt")(_.getLines)

Unfortunately, this doesn't work because getLinesis lazy (returns an iterator). And Scala doesn't have any great way to indicate which methods are lazy and which are not. So you just have to know (docs will tend to tell you), and you have to actually do the work before returning:

不幸的是,这不起作用,因为它getLines是懒惰的(返回一个迭代器)。Scala 没有任何很好的方法来表明哪些方法是惰性的,哪些不是。所以你只需要知道(文档会告诉你),并且你必须在返回之前实际完成工作:

readFile("test.txt")(_.getLines.toVector)

Overall, it's a very useful pattern. Just make sure that all accesses to the resource are completed before exiting the block (so no uncompleted futures, no lazy vals that depend on the resource, no iterators, no returning the resource itself, no streams that haven't been fully read, etc.; of course any of these things are okay if they do not depend on the open resource but only on some fully-computed quantity based upon the resource).

总的来说,这是一个非常有用的模式。只需确保在退出块之前完成对资源的所有访问(因此没有未完成的期货,没有依赖于资源的惰性值,没有迭代器,没有返回资源本身,没有尚未完全读取的流等.;当然,如果它们不依赖于开放资源,而仅依赖于基于资源的一些完全计算的数量,那么这些东西中的任何一个都可以)。

回答by le-doude

With the Loan pattern it is important to know when the "bit" of code that is going to actually call your loaned resource is going to use it.

对于贷款模式,重要的是要知道实际调用您的贷款资源的“位”代码何时将使用它。

If you want to return a future from a loan pattern I advise to not create it inside the function that is passed to the loan pattern function.

如果您想从贷款模式返回未来,我建议不要在传递给贷款模式函数的函数中创建它。

Don't write

不要写

readFile("text.file")(future { doSomething })

but do:

但做:

future { readFile("text.file")( doSomething ) }

what I usually do is that I define two types of loan pattern functions: Synchronous and Async

我通常做的是定义两种类型的贷款模式函数:同步和异步

So in your case I would have:

所以在你的情况下,我会:

def asyncReadFile[T](f: File)(handler: FileInputStream => T): Future[T] = {
  future{
    readFile(f)(handler)
  }
}

This way you avoid calling closed resources. And you reuse your already tested and hopefully correct code of the Synchronous function.

这样您就可以避免调用已关闭的资源。并且您可以重用已经测试过且希望正确的同步函数代码。