Reputation: 719
Is there a way to wrap only a return type of a passed function?
I am trying to manage resources automatically using cleanly from try-with-resources scala equivalent. What I would like to do though is to have nested managed resources, i.e. do something like:
cleanly(db.connect())(_.close()) { connection =>
cleanly(connection.prepareCall("{call procedure}"))(_.close()) { statement =>
statement.setInt("batch", 1)
statement.execute()
}
}
However that returns Try[Try[B]]. So I slightly modified the signature and implementation of the cleanly function:
def cleanly[A, B](resource: A)(cleanup: A => Unit)(doWork: A => Try[B]): Try[B] = {
try {
doWork(resource)
}
finally {
try {
if (resource != null) {
cleanup(resource)
}
} catch {
case e: Exception => log.error("Error cleaning up resource.", e) // should be logged
}
}
}
And I tried to call it from a newly added method tryCleanly which would wrap the passed function to return a Try object:
def tryCleanly[A, B](resource: A)(cleanup: A => Unit)(doWork: A => B): Try[B] = {
cleanly[A,B](resource)(cleanup)(Try(doWork))
}
However the result of doing Try(doWork) is
Try[(A) => B]
rather than
(A) => Try[B]
Is it possible to wrap only the result type of the function?
Upvotes: 0
Views: 223
Reputation: 719
@JoeK inspired me to mess around with the parameters once more, so credits go to him. What I ended up with is this:
def cleanly[A, B](resource: A)(cleanup: A => Unit)(doWork: A => Try[B]): Try[B] = {
try {
doWork(resource)
}
finally {
try {
if (resource != null) {
cleanup(resource)
}
} catch {
case e: Exception => log.error("Error cleaning up resource.", e) // should be logged
}
}
}
def tryCleanly[A, B](resource: A)(cleanup: A => Unit)(doWork: A => B): Try[B] = {
cleanly[A,B](resource)(cleanup)(resource => Try(doWork(resource)))
}
Upvotes: 0
Reputation: 18424
def tryCleanly[A, B](resource: A)(cleanup: A => Unit)(doWork: A => B): Try[B] = {
cleanly[A,B](resource)(cleanup)(a: A => Try(doWork(a)))
}
Upvotes: 1