Reputation: 22171
While reading Play! Framework documentation, I came across this snippet:
def index = Action { implicit request =>
session.get("connected").map { user =>
Ok("Hello " + user)
}.getOrElse {
Unauthorized("Oops, you are not connected")
}
}
Documentation explains implicit
there:
Alternatively you can retrieve the Session implicitly from a request
Besides, I read this post: Literal with Implicit and it seems logically that function cannot have implicit parameter.
If I well figured out, this is because a function, contrary to method has always a contract (interface).
Indeed, for instance, Function1[Int, Function1[Int, Int]]
has as a return type's first parameter an Int
, and thus prevents us to annotate this one as implicit
. This would lead to a confusion about its high-level return type: () => Int
or Int => Int
...
Therefore, what the previous snippet code behaves with implicit since first Action
's required parameter is a literal function.
I guess the reason allowing compiler to accept this code is the multiple signatures of Action.apply()
method:
def apply(block: Request[AnyContent] => Result): Action[AnyContent]
def apply(block: => Result): Action[AnyContent]
(redirecting to the first one)Since the second doesn't need some parameter, is this one selected in presence of a literal function's implicit parameter?
Upvotes: 4
Views: 809
Reputation: 4891
Consider the following code:
class MyImplicitClass(val session: Int)
object Tester {
def apply(fun: MyImplicitClass => Int): Int = ???
def apply(fun: => Int): Int = ???
}
Tester { implicit myImplicitClass => session * 20}
If this function:
def session(implicit myImplicitClass: MyImplicitClass): Int = myImplicitClass.session
is in scope, then the first code snippet will compile, because clearly the implicit parameter myImplicitClass
will be passed to the function session
in order to access the field myImplicitClass.session
, allowing you to omit the field access. This is exactly the trick the Play! Framework is using, check Controller
to find the session
function.
As a side note, the above closure is not stating that it takes an implicit parameter, it's a language feature to avoid having to do the following:
Tester { myImplicitClass =>
implicit val x = myImplicitClass
session * 20
}
when one wants to use a closure parameter as an implicit value in the body of the closure. Also note that as of Scala 2.9, you are limited to closures with exactly 1 parameter for this trick.
Upvotes: 6