2013-03-20 88 views
3

在python中,你可以避免{012} {} {{} {{} {}样板{with(见What is the python keyword "with" used for?)。我记得在Scala中看到了另一个选择,但我再也找不到它了。Scala替代蟒蛇``与`

def using[O](r: {def close()})(doit:() => O): O = try { 
    doit() 
} finally { 
    r.close 
} 

using(myWriter){() => myWriter.println("something or another")} 

它是内置到2.10,或者我需要为它单独库:

它沿着线去?

+5

这样做的最广为人知的库https://github.com/jsuereth/scala-arm,也没有,据我所知没有按阶” t开箱即用提供此功能 – 2013-03-20 08:58:34

回答

6

这几乎是微不足道的,使自己的覆盖(这里使用2.10)几乎所有的用例:

implicit class TidyUpAnything[A](val a: A) extends AnyVal { 
    def tidily[Z](g: A=>Any)(f: A=>Z) = try { f(a) } finally { g(a) } 
} 

如果你想例外通过使用如:

scala> Option(null: String).tidily(println){_.get} // Should print None 
None 
java.util.NoSuchElementException: None.get 
    at scala.None$.get(Option.scala:313) 
    ... 

和如果要处理异常,请与scala.util.Try结合使用:

scala> import scala.util._ 
scala> Try(Option(null: String).tidily(println){ _.get }) 
None 
res1: scala.util.Try[String] = Failure(java.util.NoSuchElementException: None.get) 

通常情况下,您会使g变成_.close,但您可以使用它进行任意资源清理。例如,在这里我们回到关闭的一个计数器,每当我们完成:

var i = 0 
val a = Array(1,2) 
a.tidily(_ => i -= 1){ _.foreach(_ => i += 1) } 
scala> i 
res2: Int = 1 
+0

我找到了一个类似的解决方案,但我认为应该有一些已经存在的东西。 scala-arm似乎是一种令人信服的替代方案,可以自己滚动。 – iwein 2013-03-20 09:18:40

+1

@iwein - 如果你想要的比你所要求的更多,scala-arm确实很有吸引力。仅此而已,添加依赖项而不是三行代码是一种奇怪的强制。 – 2013-03-20 09:49:36

+0

点了。你用scala-arm获得的语法可以说比你用TidyUpAnything获得的语法更好。我有点滑稽,在一般情况下添加隐含条件... – iwein 2013-03-21 06:43:45