Atif
Atif

Reputation: 129

Implicits over function closures in Scala

I've been trying to understand implicits for Scala and trying to use them at work - one particular place im stuck at is trying to pass implicits in the following manner

object DBUtils {
  case class DB(val jdbcConnection: Connection) {

    def execute[A](op: =>Unit): Any = {
        implicit val con = jdbcConnection
        op
    }
}

object DB {
    def SQL(query: String)(implicit jdbcConnection: Connection): PreparedStatement = {
      jdbcConnection.prepareStatement(query)
    }
}

val someDB1 = DB(jdbcConnection)
val someDB2 = DB(jdbcConnection2)
val someSQL = SQL("SOME SQL HERE")
someDB1.execute{someSQL} 
someDB2.execute{someSQL} 

Currently i get an execption saying that the SQL() function cannot find the implicit jdbcConnection.What gives and what do i do to make it work in the format i need?

Ps-:Im on a slightly older version of Scala(2.10.4) and cannot upgrade

Edit: Changed the problem statement to be more clear - I cannot use a single implicit connection in scope since i can have multiple DBs with different Connections

Upvotes: 0

Views: 266

Answers (3)

Nagarjuna Pamu
Nagarjuna Pamu

Reputation: 14825

Make the following changes

1) execute method take a function from Connection to Unit

2) Instead of this val someDB1 = DB(jdbcConnection) use this someDB1.execute{implicit con => someSQL}

object DBUtils {
  case class DB(val jdbcConnection: Connection) {

    def execute[A](op: Connection =>Unit): Any = {
        val con = jdbcConnection
        op(con)
    }
}

Here is the complete code.

object DB {
    def SQL(query: String)(implicit jdbcConnection: Connection): PreparedStatement = {
      jdbcConnection.prepareStatement(query)
    }
}

val someDB1 = DB(jdbcConnection)
val someDB2 = DB(jdbcConnection2)
val someSQL = SQL("SOME SQL HERE")
someDB1.execute{implicit con => someSQL} 
someDB2.execute{implicit con => someSQL} 

Upvotes: 0

radumanolescu
radumanolescu

Reputation: 4161

Try this:

implicit val con = jdbcConnection // define implicit here
val someDB = DB(jdbcConnection)
val someSQL = SQL("SOME SQL HERE") // need implicit here
someDB.execute{someSQL} 

The implicit must be defined in the scope where you need it. (In reality, it's more complicated, because there are rules for looking elsewhere, as you can find in the documentation. But the simplest thing is to make sure the implicit is available in the scope where you need it.)

Upvotes: 0

Gabriele Petronella
Gabriele Petronella

Reputation: 108121

At the point where SQL is invoked there is no implicit value of type Connection in scope.

In your code snippet the declaration of jdbcConnection is missing, but if you change it from

val jdbcConnection = //...

to

implicit val jdbcConnection = // ...

then you will have an implicit instance of Connection in scope and the compiler should be happy.

Upvotes: 1

Related Questions