user3681304
user3681304

Reputation: 719

How to wrap return type of a passed function in Scala

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

Answers (2)

user3681304
user3681304

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

Joe K
Joe K

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

Related Questions