3

In python you can avoid try {} catch {} finally {} boilerplate with with (see What is the python keyword "with" used for?). I remember seeing an alternative to that in Scala, but I can't find it anymore.

It goes along the lines of:

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

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

Is it built into 2.10, or do I need a separate library for it?

Community
  • 1
  • 1
iwein
  • 25,788
  • 10
  • 70
  • 111
  • 5
    Most widely known library for doing this is https://github.com/jsuereth/scala-arm, and no, AFAIK scala doesn't provide this feature out-of-the-box – om-nom-nom Mar 20 '13 at 08:58

1 Answers1

6

It's almost trivial to make your own that covers almost all use cases (here using 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) }
}

If you want exceptions to pass through, use as is:

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

and if you want to handle exceptions, use it in conjunction with 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)

Normally you would make g be something like _.close, but you can do arbitary resource cleanup with it. For example, here we back off a counter by one whenever we finish:

var i = 0
val a = Array(1,2)
a.tidily(_ => i -= 1){ _.foreach(_ => i += 1) }
scala> i
res2: Int = 1
Rex Kerr
  • 166,841
  • 26
  • 322
  • 407
  • I came to a similar solution, but I was thinking there should be something out there that already had this. scala-arm seems a compelling alternative to rolling your own. – iwein Mar 20 '13 at 09:18
  • 1
    @iwein - If you want more than what you asked for, scala-arm is indeed compelling. For this alone, adding a dependency instead of three lines of code is a strange compulsion. – Rex Kerr Mar 20 '13 at 09:49
  • point taken. The syntax that you get with scala-arm is arguably nicer than the one you get with TidyUpAnything. I'm somewhat skiddish of adding implicits for generic situations... – iwein Mar 21 '13 at 06:43
  • 1
    @iwein - You are perfectly free to `def tidily[A,Z](resource: A)(tidy: A => Any)(act: A=>Z) = try { act(resource) } finally { tidy(resource) }` if you prefer a one-liner without implicits. scala-arm has syntax better tailored for some scenarios, agreed. – Rex Kerr Mar 21 '13 at 12:01