Reputation: 1202
How can I avoid duplicating the if
condition in my code:
def download() =
Action {
val out = new FileWriter("/tmp/foo.txt")
Try {
val chars = new Array[Char](1024)
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
} match {
case Failure(_) =>
if (out != null) out.close()
println("failed")
case Success(_) =>
if (out != null) out.close()
println("success")
}
}
I tried to adapt from the following:
def download() =
Action {
Try {
val out = new FileWriter("/tmp/foo.txt")
try{
val chars = new Array[Char](1024)
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
} if (out != null) out.close()
} match {
case Failure(_) =>
println("failed")
case Success(_) =>
println("success")
}
}
But that way I have a Java try
inside a Scala Try
which doesn't seem right. How do I avoid having two try blocks? I basically just want the resource I acquired cleaned up after the method finishes executing.
Upvotes: 0
Views: 79
Reputation: 27535
If you cannot use Using
you can use try-catch-finally
:
def download() =
Action {
val out = new FileWriter("/tmp/foo.txt")
try {
val chars = new Array[Char](1024)
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
println("success")
} catch {
case _: Throwable =>
println("failed")
} finally {
out.close()
}
}
or loan pattern:
def withFileWriter[A](str: String)(f: FileWriter => A): Try[A] = Try {
val out = new FileWriter("/tmp/foo.txt")
try {
f(out)
} finally {
out.close()
}
}
withFileWriter("/tmp/foo.txt"){ out =>
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
} match {
case Failure(_) =>
println("failed")
case Success(_) =>
println("success")
}
If you have Cats Effect (and if you replace Try with something that is lawful), you can use Resource
val resource = Resource.make {
IO(new FileWriter("/tmp/foo.txt"))
} { out =>
IO(out.close())
}
resource.use(out => IO {
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
}).attempt.map {
case Failure(_) =>
println("failed")
case Success(_) =>
println("success")
}.unsafeRunSync
Upvotes: 1
Reputation: 3474
Why not just move the out.close()
outside of the result of the Try block? If the same check is performed regardless of if it's a success or failure, I don't see the benefit of doing it there. Something like this:
def download() = Action {
val out = new FileWriter("/tmp/foo.txt")
Try {
val chars = new Array[Char](1024)
util.Arrays.fill(chars, '.')
chars(1024) = '\n'
out.write(chars)
} match {
case Failure(_) =>
println("failed")
case Success(_) =>
println("success")
}
if (out != null) out.close()
}
Upvotes: 1
Reputation: 7275
With scala 2.13, you could write the following with the help of scala.util.Using
import scala.util.Failure
import scala.util.Success
import scala.util.Using
Using(new FileWriter("/tmp/foo.txt")) { out =>
val chars = new Array[Char](1024)
java.util.Arrays.fill(chars, '.')
chars(1023) = '\n'
out.write(chars)
} match {
case Failure(_) =>
println("failed")
case Success(_) =>
println("success")
}
Upvotes: 1