How can I express *finally* equivalent for a Scala's Try?

Viewed 2857

How do I translate the following Java code to Scala using the new Try API?

public byte[] deflate(byte[] data) {

    ByteArrayOutputStream outputStream = null;
    GZIPOutputStream gzipOutputStream = null;

    try {
        outputStream = new ByteArrayOutputStream();
        gzipOutputStream = new GZIPOutputStream(outputStream);
        gzipOutputStream.write(data);
        return outputStream.toByteArray();
    catch (Exception e) {
        ...
    } finally {
        if (gzipOutputStream != null) gzipOutputStream.close();
    }
}

The Scala version should be something like this...

def deflate(data Array[Byte]): Try[Array[Byte]] = Try {
  ByteArrayOutputStream outputStream = new ByteArrayOutputStream()
  new GZIPOutputStream(outputStream).write(data)
  outputStream.toByteArray
}

... but how do I implement Java's finally equivalent?

3 Answers

Choppy's Lazy TryClose monad is made for this kind of scenario where you want try-with-resources. Plus, it's lazy so you can compose stuff.

Here is an example of how you would use it:

val output = for {
  outputStream      <- TryClose(new ByteArrayOutputStream())
  gzipOutputStream  <- TryClose(new GZIPOutputStream(outputStream))
  _                 <- TryClose.wrap(gzipOutputStream.write(data))
} yield wrap(outputStream.toByteArray())

// Does not actually run anything until you do this:
output.resolve.unwrap match {
    case Success(bytes) => // do something with bytes
    case Failure(e) => // handle exception
}

More info here: https://github.com/choppythelumberjack/tryclose

(just be sure to import tryclose._ and tryclose.JavaImplicits._)

Related