0

I am trying to understand database connections in Scala using the default Anorm library in play framework. Play has a sample example "Computer Database" where one of the functions tries to retrieve a computer from the DB:

DB.withConnection { implicit connection =>
  SQL("select * from computer where id = {id}").on('id -> id).as(Computer.simple.singleOpt)
}

If I look at the function signature of withConnection it is this:

def withConnection [A] (block: (Connection) ⇒ A)(implicit app: Application): A
Execute a block of code, providing a JDBC connection. The connection and all created statements are automatically released.
**block** Code block to execute.

My question is how to map each value of function call to function definition? For example what is A (is it the whole SQL query, but what does the return type mean then?). What the implicit app in this case? Where is it defined?

Richeek
  • 2,068
  • 2
  • 29
  • 37

1 Answers1

3

admittedly this example is confusing, since it combines several language features

  1. type parameters (generics)
  2. currying (=two argument lists)
  3. anonymous inline function (function block)
  4. implicit arguments (which are picked up from the context)

As always, when matters start to become complicated, lets' sort it out one by one

(1) A is a type parameter. This is replaced by a suitable type on each invocation of the function. Since A is mentioned at two locations in the argument list and in the return type, this means that whatever type you use, the result type of the passed-in function block will be the same than the overall return type. You could explicitly define A when using the function, but typically you can leave it out, since the compiler can infer the actual type used.

(2) currying is easy to understand. This function here just has two parameter lists. Which means you can apply this function in several steps. First apply the left parameter list:

def myBlock(connection:Connection):SQL =
        SQL("select ......" .....

val pf = DB.withConnection(myBlock)

Question: what kind of Object is pf ? what is ists type? Answer: it is a function, taking one argument, an Application object

Thus the type of pf would be Application => SQL since in the first, partial application of the function, we just passed in another function with return type SQL, thus type parameter A is inferred to be SQL

(3) but in the code above, we've defined the function myBlock in a conventional fashion, and we gave it explicitly the name "myBlock". This isn't necessary. We can define the same function just inline, using the block syntax.

(4) and now the confusing, "magic" part, the implicits. This is a very special feature of Scala, where the compiler allows you to omit some values, or arguments (in our case). You may not omit arbitrary arguments, but only arguments marked as implicit. When you do so, the compiler doesn't immediately generate an error; rather it looks in the current scope, if he can find some suitable other object with the same name.

Effectively this means, that in your example, there must somehow be an value "connection" of type Connection, and there must be a value "application" of type Application. Both values must be visible somehow in the current scope -- that is, either as parameter, as value in an enclosing scope, or as value in the companion object, or you might have brought them into scope explicitly with an import statement. The purpose of this language feature is just to save you typing those obvious arguments (application and connection9 again and again

Ichthyo
  • 8,038
  • 2
  • 26
  • 32
  • I understand what you are saying one question though: This SQL query is defined in `package models` which is being imported in `object Application` so how does that make `Application` object visible for implicit definition `implicit app: Application` – Richeek Nov 25 '13 at 06:06
  • can't give you a precise answer, I'd have to look at the code. sorry. Just a guess: maybe it is iherited? or maybe it was imported expliticly into an enclosing scope or parent class? – Ichthyo Nov 25 '13 at 06:56
  • I will check that tomorrow...one more thing the example you provided `def myBlock(connection:Connection):SQL = ...` does not work as such. I have to import `java.sql.Connection` for it to find `Connection` class. However `implicit connection =>...` works without importing it. Its confusing! – Richeek Nov 25 '13 at 07:11