[scala] Understanding implicit in Scala

In scala implicit works as:

Converter

Parameter value injector

Extension method

There are 3 types of use of Implicit

  1. 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

implicit def z(a:String):Int = 2

val x :String = "1"

val y:Int = x // compiler will use z here like val y:Int=z(x)

println(y) // result 2  & no error!
  1. 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.

     class Mahadi{
    
     val haveCar:String ="BMW"
    
     }
    

    class Johnny{

    val haveTv:String = "Sony"

    }

   val mahadi = new Mahadi



   mahadi.haveTv // Error happening

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.

class Mahadi{

val haveCar:String ="BMW"

}

class Johnny{

val haveTv:String = "Sony"

}

val mahadi = new Mahadi

implicit def z(a:Mahadi):Johnny = new Johnny

mahadi.haveTv // compiler will use z here like new Johnny().haveTv

println(mahadi.haveTv)// result Sony & no error
  1. 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.

     def x(a:Int)= a
    
     x // ERROR happening
    

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.

def x(implicit a:Int)= a

x // error happening here

To slove this problem compiler will look for a implicit val having the type of Int because the parameter a has implicit keyword.

def x(implicit a:Int)=a

implicit val z:Int =10

x // compiler will use implicit like this x(z)
println(x) // will result 10 & no error.

Another example:

def l(implicit b:Int)

def x(implicit a:Int)= l(a)

we can also write it like-

def x(implicit a:Int)= l

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

 def x(implicit a:Int)= l

will be in compiler like this

def x(implicit a:Int)= l(a)

Another example:

def c(implicit k:Int):String = k.toString

def x(a:Int => String):String =a

x{
x => c
}

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

x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}

This has been used in action method of Play-Framework

in view folder of app the template is declared like
@()(implicit requestHreader:RequestHeader)

in controller action is like

def index = Action{
implicit request =>

Ok(views.html.formpage())  

}

if you do not mention request parameter as implicit explicitly then you must have been written-

def index = Action{
request =>

Ok(views.html.formpage()(request))  

}
  1. Extension Method

Think, we want to add new method with Integer object. The name of the method will be meterToCm,

> 1 .meterToCm 
res0 100 

to do this we need to create an implicit class within a object/class/trait . This class can not be a case class.

object Extensions{
    
    implicit class MeterToCm(meter:Int){
        
        def  meterToCm={
             meter*100
        }

    }

}

Note the implicit class will only take one constructor parameter.

Now import the implicit class in the scope you are wanting to use

import  Extensions._

2.meterToCm // result 200

Examples related to scala

Intermediate language used in scalac? Why does calling sumr on a stream with 50 tuples not complete Select Specific Columns from Spark DataFrame Joining Spark dataframes on the key Provide schema while reading csv file as a dataframe how to filter out a null value from spark dataframe Fetching distinct values on a column using Spark DataFrame Can't push to the heroku Spark - Error "A master URL must be set in your configuration" when submitting an app Add jars to a Spark Job - spark-submit

Examples related to syntax

What is the 'open' keyword in Swift? Check if returned value is not null and if so assign it, in one line, with one method call Inline for loop What does %>% function mean in R? R - " missing value where TRUE/FALSE needed " Printing variables in Python 3.4 How to replace multiple patterns at once with sed? What's the meaning of "=>" (an arrow formed from equals & greater than) in JavaScript? How can I fix MySQL error #1064? What do >> and << mean in Python?

Examples related to playframework

Error: Argument is not a function, got undefined Understanding implicit in Scala How do I change the default port (9000) that Play uses when I execute the "run" command?

Examples related to keyword

How to select data from 30 days? How to use "raise" keyword in Python Python: SyntaxError: keyword can't be an expression Understanding implicit in Scala How do I create sql query for searching partial matches? What is the native keyword in Java for? Difference between "this" and"super" keywords in Java Equivalent of "continue" in Ruby What is the equivalent of the C# 'var' keyword in Java? Is there a goto statement in Java?