Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding implicit in Scala

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?

like image 247
Clive Avatar asked Apr 29 '12 20:04

Clive


People also ask

What does implicit mean in Scala?

Implicit parameters are the parameters that are passed to a function with implicit keyword in Scala, which means the values will be taken from the context in which they are called.

What is implicit in spark?

implicits object gives implicit conversions for converting Scala objects (incl. RDDs) into a Dataset , DataFrame , Columns or supporting such conversions (through Encoders).

What is an implicit parameter?

What Are Implicit Parameters? Implicit parameters are similar to regular method parameters, except they could be passed to a method silently without going through the regular parameters list. A method can define a list of implicit parameters, that is placed after the list of regular parameters.

Why does Scala have Implicits?

Scala provides an implicit keyword that can be used in two ways: method or variable definitions, and method parameter lists. If this keyword is used on method or variable definitions, it tells the compiler that those methods or variable definitions can be used during implicit resolution.


1 Answers

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 implicit Int!

example:

  // probably in a library class Prefixer(val prefix: String) def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s    // then probably in your application implicit val myImplicitPrefixer = new Prefixer("***") addPrefix("abc")  // returns "***abc" 

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 an A is required and it finds a B, it will look for an implicit value of type B => A in scope (it also checks some other places like in the B and A companion objects, if they exist). Since defs can be "eta-expanded" into Function objects, an implicit 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 a Double is found but an Int is required.

implicit def doubleToInt(d: Double) = d.toInt val x: Int = 42.0 

will work the same as

def doubleToInt(d: Double) = d.toInt val x: Int = doubleToInt(42.0) 

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

apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent] 

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

request => ... 

In a function literal, the part before the => is a value declaration, and can be marked implicit if you want, just like in any other val declaration. Here, request doesn't have to be marked implicit 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 the bindFromRequest method on the Form class requires an implicit Request argument.

like image 127
Luigi Plinge Avatar answered Sep 18 '22 13:09

Luigi Plinge