I was making my way through the Scala playframework tutorial and I came across this snippet of code which had me puzzled:
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
So I decided to investigate and came across this post.
I still don't get it.
What is the difference between this:
implicit def double2Int(d : Double) : Int = d.toInt
and
def double2IntNonImplicit(d : Double) : Int = d.toInt
other than the obvious fact they have different method names.
When should I use implicit
and why?
In scala implicit works as:
Converter
Parameter value injector
There are 3 types of use of Implicit
Implicitly type conversion : It converts the error producing assignment into intended type
val x :String = "1"
val y:Int = x
String is not the sub type of Int , so error happens in line 2. To resolve the error the compiler will look for such a method in the scope which has implicit keyword and takes a String as argument and returns an Int .
so
Implicitly receiver conversion: We generally by receiver call object's properties, eg. methods or variables . So to call any property by a receiver the property must be the member of that receiver's class/object.
Here mahadi.haveTv will produce an error. Because scala compiler will first look for the haveTv property to mahadi receiver. It will not find. Second it will look for a method in scope having implicit keyword which take Mahadi object as argument and returns Johnny object. But it does not have here. So it will create error. But the following is okay.
Implicitly parameter injection: If we call a method and do not pass its parameter value, it will cause an error. The scala compiler works like this - first will try to pass value, but it will get no direct value for the parameter.
Second if the parameter has any implicit keyword it will look for any val in the scope which have the same type of value. If not get it will cause error.
To slove this problem compiler will look for a implicit val having the type of Int because the parameter a has implicit keyword.
Another example:
we can also write it like-
Because l has a implicit parameter and in scope of method x's body, there is an implicit local variable(parameters are local variables) a which is the parameter of x, so in the body of x method the method-signature l's implicit argument value is filed by the x method's local implicit variable(parameter)
a
implicitly.So
will be in compiler like this
Another example:
it will cause error, because c in x{x=>c} needs explicitly-value-passing in argument or implicit val in scope.
So we can make the function literal's parameter explicitly implicit when we call the method x
This has been used in action method of Play-Framework
if you do not mention request parameter as implicit explicitly then you must have been written-
A very basic example of Implicits in scala.
Implicit parameters:
Note: Here
multiplier
will be implicitly passed into the functionmultiply
. Missing parameters to the function call are looked up by type in the current scope meaning that code will not compile if there is no implicit variable of type Int in the scope.Implicit conversions:
Note: When we call
multiply
function passing a double value, the compiler will try to find the conversion implicit function in the current scope, which convertsInt
toDouble
(As functionmultiply
acceptInt
parameter). If there is no implicitconvert
function then the compiler will not compile the code.I'll explain the main use cases of implicits below, but for more detail see the relevant chapter of Programming in Scala.
Implicit parameters
The final parameter list on a method can be marked
implicit
, which means the values will be taken from the context in which they are called. If there is no implicit value of the right type in scope, it will not compile. Since the implicit value must resolve to a single value and to avoid clashes, it's a good idea to make the type specific to its purpose, e.g. don't require your methods to find an implicitInt
!example:
Implicit conversions
When the compiler finds an expression of the wrong type for the context, it will look for an implicit
Function
value of a type that will allow it to typecheck. So if anA
is required and it finds aB
, it will look for an implicit value of typeB => A
in scope (it also checks some other places like in theB
andA
companion objects, if they exist). Sincedef
s can be "eta-expanded" intoFunction
objects, animplicit def xyz(arg: B): A
will do as well.So the difference between your methods is that the one marked
implicit
will be inserted for you by the compiler when aDouble
is found but anInt
is required.will work the same as
In the second we've inserted the conversion manually; in the first the compiler did the same automatically. The conversion is required because of the type annotation on the left hand side.
Regarding your first snippet from Play:
Actions are explained on this page from the Play documentation (see also API docs). You are using
on the
Action
object (which is the companion to the trait of the same name).So we need to supply a Function as the argument, which can be written as a literal in the form
In a function literal, the part before the
=>
is a value declaration, and can be markedimplicit
if you want, just like in any otherval
declaration. Here,request
doesn't have to be markedimplicit
for this to type check, but by doing so it will be available as an implicit value for any methods that might need it within the function (and of course, it can be used explicitly as well). In this particular case, this has been done because thebindFromRequest
method on the Form class requires an implicitRequest
argument.Why and when you should mark the
request
parameter asimplicit
:Some methods that you will make use of in the body of your action have an implicit parameter list like, for example, Form.scala defines a method:
You don't necessarily notice this as you would just call
myForm.bindFromRequest()
You don't have to provide the implicit arguments explicitly. No, you leave the compiler to look for any valid candidate object to pass in every time it comes across a method call that requires an instance of the request. Since you do have a request available, all you need to do is to mark it asimplicit
.You explicitly mark it as available for implicit use.
You hint the compiler that it's "OK" to use the request object sent in by the Play framework (that we gave the name "request" but could have used just "r" or "req") wherever required, "on the sly".
see it? it's not there, but it is there!
It just happens without your having to slot it in manually in every place it's needed (but you can pass it explicitly, if you so wish, no matter if it's marked
implicit
or not):Without marking it as implicit, you would have to do the above. Marking it as implicit you don't have to.
When should you mark the request as
implicit
? You only really need to if you are making use of methods that declare an implicit parameter list expecting an instance of the Request. But to keep it simple, you could just get into the habit of marking the requestimplicit
always. That way you can just write beautiful terse code.Also, in the above case there should be
only one
implicit function whose type isdouble => Int
. Otherwise, the compiler gets confused and won't compile properly.WARNING: contains sarcasm judiciously! YMMV...
Luigi's answer is complete and correct. This one is only to extend it a bit with an example of how you can gloriously overuse implicits, as it happens quite often in Scala projects. Actually so often, you can probably even find it in one of the "Best Practice" guides.