16
def doWork() = {
  getLock()
  Try(useResource) match {
    case Success(result) => releaseLock(); result
    case Failure(e: Exception) => releaseLock(); throw e
  }
}

I'm trying to idiomatically make sure a lock is released when I exit doWork. However as part of that method I may throw an exception, so I can't just release the lock at the end of doWork.

It looks like a bit of code smell to have releaseLock() repeated twice. I could cut that down by using the traditional Java-style try/catch/finally:

def doWork() = {
  getLock()
  try {
    useResource
  } catch {
    case e: Exception => throw e
  } finally {
    releaseLock()
  }
}

But I prefer to use Scala's Try if possible.

Is there a way to perform "finally" logic from within the framework of Try?

Cory Klein
  • 51,188
  • 43
  • 183
  • 243
  • 1
    Your two versions aren't the same. The second one returns the result of `useResource`; the first one discards that value and returns the result of `releaseLock`. – Sean Nov 12 '15 at 22:26
  • @Sean For the purposes of the question whatever `doWork` returns isn't really relevant, but I'll update the question to prevent any further confusion. – Cory Klein Nov 12 '15 at 22:31
  • If you are using something implements the java.lang.AutoCloseable, you can use the code at the answer below to implement a standard "finally" pattern. You can also easily refactor the code in the answer below to retarget it to your specific resource API: http://stackoverflow.com/questions/4604237/how-to-write-to-a-file-in-scala/34277491#34277491 – chaotic3quilibrium Oct 01 '16 at 22:26
  • 1
    This question/answer is much better than the duplicate. – Andy Hayden May 21 '18 at 21:17

1 Answers1

21

Just squirrel the Try away temporarily:

def doWork = {
  getLock()
  val t = Try(useResource)
  releaseLock()
  t.get
}
Sean
  • 29,130
  • 4
  • 80
  • 105