(I am fairly new to Scala, hope this isn't a stupid question.)
From what I can see, declaring a parameter to a function implicit has two (related, but quite different) uses:
It makes explicitly passing a corresponding argument when calling the given function optional when the compiler can find a unique suitable value to pass (in the calling scope).
It makes the parameter itself a suitable value to pass to other functions with implicit parameters (when calling them from within the given function).
In code:
def someFunction(implicit someParameter: SomeClass) = { // Note `implicit`
...
// Note no argument supplied in following call;
// possible thanks to the combination of
// `implicit` in `someOtherFunction` (1) and
// `implicit` in line 1 above (2)
someOtherFunction
...
}
def someOtherFunction(implicit someOtherParameter: SomeClass) = {
...
}
implicit val someValue = new SomeClass(...)
// Note no argument supplied in following call;
// possible thanks to `implicit` (1)
someFunction
This seems somewhat strange, doesn't it? Removing implicit from line 1 would make both calls (to someFunction from some other place, and to someOtherFunction from within someFunction) not compile.
What is the rationale behind this? (Edit: I mean what is the official rationale, in case any can be found in some official Scala resource.)
And is there a way to achieve one without the other (that is to allow passing an argument to a function implicitly without allowing it to be used implicitly within that function when calling other functions, and/or to use a non-implicit parameter implicitly when calling other functions)? (Edit: I changed the question a bit. Also, to clarify, I mean whether there is a language construct to allow this - not achieving the effect by manual shadowing or similar.)
For the first question
What is the rationale behind this?
answers are likely to be opinion-based.
And is there a way to achieve one without the other?
Yes, though it's a bit trickier than I thought initially if you want to actually use the parameter:
def someFunction(implicit someParameter: SomeClass) = {
val _someParameter = someParameter // rename to make it accessible in the inner block
{
val someParameter = 0 // shadow someParameter by a non-implicit
someOtherFunction // doesn't compile
someOtherFunction(_someParameter) // passed explicitly
}
}
The rationale is simple:
What has been passed as explicit, stays explicit
What has been marked as implicit, stays implicit
I don't think that any other combination (e.g. implicit -> explicit, let alone explicit -> implicit) would be easier to understand. The basic idea was, I think, that one can establish some common implicit context, and then define whole bunch of methods that expect same implicit variables that describe the established context.
Here is how you can go from implicit to explicit and back:
Implicit -> implicit (default)
def foo(implicit x: Int): Unit = {
bar
}
def bar(implicit x: Int): Unit = {}
Explicit -> implicit:
def foo(x: Int): Unit = {
implicit val implicitX = x
bar
}
def bar(implicit x: Int): Unit = {}
Implicit -> explicit: I would just use Alexey Romanov's solution, but one could imagine that if we had the following method in Predef:
def shadowing[A](f: Unit => A): A = f(())
then we could write something like this:
def foo(implicit x: Int): Unit = {
val explicitX = x
shadowing { x =>
// bar // doesn't compile
bar(explicitX) // ok
}
}
def bar(implicit x: Int): Unit = {}
Essentially, it's the same as Alexey Romanov's solution: we introduce a dummy variable that shadows the implicit argument, and then write the body of the method in the scope where only the dummy variable is visible. The only difference is that a ()-value is passed inside the shadowing implementation, so we don't have to assign a 0 explicitly. It doesn't make the code much shorter, but maybe it expresses the intent a little bit clearer.
Related
I wonder if it's possible to modify an implicit in a context with a function?
With a syntax like this
def modifyImplicit(implicit myImplicit: ImplicitType) : implicit ImplicitType {
myImplicit.setSomthing(something)
myImplicit
}
Because now I must return a type and after the function transform this in a new implicit
if I need to use the function more than once it's became quickly painful.
That's would introduce side-effect (automagically alter the environment without much notice), with it's not "very good".
Instead you can allow some operation to be executed within a managed context, in which you explicitly provide a replacement for the implicit.
implicit def TheDefaultTypeClass: ImplicitType
def withMyContext[T](f: (ImplicitType) => T): T = f(anotherTypeClass)
Then it can be used as following:
val s: String = withMyContext { i =>
val x: ImplicitType = i // Dumb statement just to check type of `i`
// some operations ...
"OK" // result
}
No, it isn't possible. You could write
implicit def modifyImplicit(implicit myImplicit: ImplicitType): ImplicitType = ...
but this won't work the way you want (because for it to ever be called, an implicit of this type must already be available, so either the compiler won't continue looking for an implicit or it will and report conflicting implicits).
Also, having a mutable implicit value seems very likely to lead to bugs.
One possible workaround (in addition to the method proposed by applicius): extract your code into a method and call it with a modified implicit value.
def myMethod(args: ...)(implicit i: ImplicitType) = ...
myMethod(args)(modifyImplicit(implicitly[ImplicitType]))
Yes I now but implicit are mutable because :
```
def modifyImplicit(implicit myImplicit: ImplicitType) {
implicit val myNewImplicit = myImplicit.setSomthing(something)
imASweetMethodWitchUseImplicit
....
}
```
imASweetMethodWitchUseImplicit will use the last implicit setted in the context so we can't "stuck the imutability of the implicit"
I's actually the way i use to made what I whan but I thinks it's a little bit ugly.
I do that for "preparing" the context for other's function so I'm confident because it's just the variable whitch are hide not the call of my function ( witch modify the variables ) you know?
so Alexey I use the same option than you,but I take directly un implicit.
If I call more than one function it's become ugly
```
val result = modifyImplicit()
val result2 = modifyImplicit(result)
implicit val result3 = modifyImplicit(result2)
```
So maybe the solution of applicius can be more beautiful ?
I'm defining some Scala implicits to make working with a particular unchangeable set of Java classes easier. The following Scala code is a simplified example that obviously looks crazy, in the real world I'm trying to grab particular resources (rather than numeric age) implicitly from the Monkey, Tree & Duck for use in various methods like purchaseCandles():
// actually 3 Java classes I can not change:
case class Monkey(bananas: Int)
case class Tree(rings: Int)
case class Duck(quacks: Seq[String])
// implicits I created to make my life easier...
implicit def monkey2Age(monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(tree: Tree): Int = tree.rings
implicit def duck2Age(duck: Duck): Int = duck.quacks.size / 100000
// one of several helper methods that I would like to define only once,
// only useful if they can use an implicit parameter.
def purchaseCandles()(implicit age: Int) = {
println(s"I'm going to buy $age candles!")
}
// examples of usage
{
implicit val guest = Monkey(10000)
purchaseCandles()
}
{
implicit val guest = Tree(50)
purchaseCandles()
}
{
implicit val guest = Duck(Seq("quack", "quack", "quack"))
purchaseCandles()
}
The compiler error, which occurs 3 times:
could not find implicit value for parameter age: Int
purchaseCandles()
^
Leaving aside the many different ways in which this sample code is crazy, my real question is: can implicit conversions of implicit values satisfy implicit parameters in Scala?
Short answer: no. Scala's compiler will only ever look to apply a single implicit, so if it fails to spot an implicit int lying around, it will stop and give up.
However, you could write your purchaseCandles method to operate on types that can be converted to an Int, and require a parameter of that type:
def purchaseCandles[A <% Int]()(implicit age : A) = {
val asAge : Int = age
println(s"I'm going to buy $asAge candles!")
}
The asAge part is necessary to force the application of the implicit conversion.
As of yet, I seem to need to specify the type of A in this scenario, though I can't work out why: since there shouldn't be other values around of types that can be implicitly converted to Int (this happens with brand new types as well, so it's not the ubiquity of Int.) But you can do:
{
implicit val guest = Monkey(10000)
purchaseCandles[Monkey]()
}
This use of implicits, however, is probably a bad idea!
You actually can do that: You just have to mark the parameters of your implicit conversion as implicit as well:
implicit def monkey2Age(implicit monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(implicit tree: Tree): Int = tree.rings
implicit def duck2Age(implicit duck: Duck): Int = duck.quacks.size / 100000
This will chain the implicits they way you want.
As always: Beware, it will also do so in places you don't want it to. By the way, I strongly advise against an implicit parameter of type Int (or an implicit value thereof). It is just too generic. (I'm somewhat assuming this is just like that in your example).
I understand the difference between zero-parameter and parameterless methods, but what I don't really understand is the language design choice that made parameterless methods necessary.
Disadvantages I can think of:
It's confusing. Every week or two there are questions here or on the Scala mailing list about it.
It's complicated; we also have to distinguish between () => X and => X.
It's ambiguous: does x.toFoo(y) mean what it says, or x.toFoo.apply(y)? (Answer: it depends on what overloads there are x's toFoo method and the overloads on Foo's apply method, but if there's a clash you don't see an error until you try to call it.)
It messes up operator style method calling syntax: there is no symbol to use in place of the arguments, when chaining methods, or at the end to avoid semicolon interference. With zero-arg methods you can use the empty parameter list ().
Currently, you can't have both defined in a class: you get an error saying the method is already defined. They also both convert to a Function0.
Why not just make methods def foo and def foo() exactly the same thing, and allow them to be called with or without parentheses? What are the upsides of how it is?
Currying, That's Why
Daniel did a great job at explaining why parameterless methods are necessary. I'll explain why they are regarded distinctly from zero-parameter methods.
Many people view the distinction between parameterless and zero-parameter functions as some vague form of syntactic sugar. In truth it is purely an artifact of how Scala supports currying (for completeness, see below for a more thorough explanation of what currying is, and why we all like it so much).
Formally, a function may have zero or more parameter lists, with zero or more parameters each.
This means the following are valid: def a, def b(), but also the contrived def c()() and def d(x: Int)()()(y: Int) etc...
A function def foo = ??? has zero parameter lists. A function def bar() = ??? has precisely one parameter list, with zero parameters. Introducing additional rules that conflate the two forms would have undermined currying as a consistent language feature: def a would be equivalent in form to def b() and def c()() both; def d(x: Int)()()(y: Int) would be equivalent to def e()(x: Int)(y: Int)()().
One case where currying is irrelevant is when dealing with Java interop. Java does not support currying, so there's no problem with introducing syntactic sugar for zero-parameter methods like "test".length() (which directly invokes java.lang.String#length()) to also be invoked as "test".length.
A quick explanation of currying
Scala supports a language feature called 'currying', named after mathematician Haskell Curry.
Currying allows you to define functions with several parameter lists, e.g.:
def add(a: Int)(b: Int): Int = a + b
add(2)(3) // 5
This is useful, because you can now define inc in terms of a partial application of add:
def inc: Int => Int = add(1)
inc(2) // 3
Currying is most often seen as a way of introducing control structures via libraries, e.g.:
def repeat(n: Int)(thunk: => Any): Unit = (1 to n) foreach { _ => thunk }
repeat(2) {
println("Hello, world")
}
// Hello, world
// Hello, world
As a recap, see how repeat opens up another opportunity to use currying:
def twice: (=> Any) => Unit = repeat(2)
twice {
println("Hello, world")
}
// ... you get the picture :-)
One nice thing about an issue coming up periodically on the ML is that there are periodic answers.
Who can resist a thread called "What is wrong with us?"
https://groups.google.com/forum/#!topic/scala-debate/h2Rej7LlB2A
From: martin odersky Date: Fri, Mar 2, 2012 at
12:13 PM Subject: Re: [scala-debate] what is wrong with us...
What some people think is "wrong with us" is that we are trying bend
over backwards to make Java idioms work smoothly in Scala. The
principaled thing would have been to say def length() and def length
are different, and, sorry, String is a Java class so you have to write
s.length(), not s.length. We work really hard to paper over it by
admitting automatic conversions from s.length to s.length(). That's
problematic as it is. Generalizing that so that the two are identified
in the type system would be a sure way to doom. How then do you
disambiguate:
type Action = () => () def foo: Action
Is then foo of type Action or ()? What about foo()?
Martin
My favorite bit of paulp fiction from that thread:
On Fri, Mar 2, 2012 at 10:15 AM, Rex Kerr <ich...#gmail.com> wrote:
>This would leave you unable to distinguish between the two with
>structural types, but how often is the case when you desperately
>want to distinguish the two compared to the case where distinguishing
>between the two is a hassle?
/** Note to maintenance programmer: It is important that this method be
* callable by classes which have a 'def foo(): Int' but not by classes which
* merely have a 'def foo: Int'. The correctness of this application depends
* on maintaining this distinction.
*
* Additional note to maintenance programmer: I have moved to zambia.
* There is no forwarding address. You will never find me.
*/
def actOnFoo(...)
So the underlying motivation for the feature is to generate this sort of ML thread.
One more bit of googlology:
On Thu, Apr 1, 2010 at 8:04 PM, Rex Kerr <[hidden email]> wrote: On
Thu, Apr 1, 2010 at 1:00 PM, richard emberson <[hidden email]> wrote:
I assume "def getName: String" is the same as "def getName(): String"
No, actually, they are not. Even though they both call a method
without parameters, one is a "method with zero parameter lists" while
the other is a "method with one empty parameter list". If you want to
be even more perplexed, try def getName()(): String (and create a
class with that signature)!
Scala represents parameters as a list of lists, not just a list, and
List() != List(List())
It's kind of a quirky annoyance, especially since there are so few
distinctions between the two otherwise, and since both can be
automatically turned into the function signature () => String.
True. In fact, any conflation between parameterless methods and
methods with empty parameter lists is entirely due to Java interop.
They should be different but then dealing with Java methods would be
just too painful. Can you imagine having to write str.length() each
time you take the length of a string?
Cheers
First off, () => X and => X has absolutely nothing to do with parameterless methods.
Now, it looks pretty silly to write something like this:
var x() = 5
val y() = 2
x() = x() + y()
Now, if you don't follow what the above has to do with parameterless methods, then you should look up uniform access principle. All of the above are method declarations, and all of them can be replaced by def. That is, assuming you remove their parenthesis.
Besides the convention fact mentioned (side-effect versus non-side-effect), it helps with several cases:
Usefulness of having empty-paren
// short apply syntax
object A {
def apply() = 33
}
object B {
def apply = 33
}
A() // works
B() // does not work
// using in place of a curried function
object C {
def m()() = ()
}
val f: () => () => Unit = C.m
Usefulness of having no-paren
// val <=> def, var <=> two related defs
trait T { def a: Int; def a_=(v: Int): Unit }
trait U { def a(): Int; def a_=(v: Int): Unit }
def tt(t: T): Unit = t.a += 1 // works
def tu(u: U): Unit = u.a += 1 // does not work
// avoiding clutter with apply the other way round
object D {
def a = Vector(1, 2, 3)
def b() = Vector(1, 2, 3)
}
D.a(0) // works
D.b(0) // does not work
// object can stand for no-paren method
trait E
trait F { def f: E }
trait G { def f(): E }
object H extends F {
object f extends E // works
}
object I extends G {
object f extends E // does not work
}
Thus in terms of regularity of the language, it makes sense to have the distinction (especially for the last shown case).
I would say both are possible because you can access mutable state with a parameterless method:
class X(private var x: Int) {
def inc() { x += 1 }
def value = x
}
The method value does not have side effects (it only accesses mutable state). This behavior is explicitly mentioned in Programming in Scala:
Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).
This convention supports the uniform access principle [...]
To summarize, it is encouraged style in Scala to define methods that take no parameters and have no side effects as parameterless methods, i.e., leaving off the empty parentheses. On the other hand, you should never define a method that has side-effects without parentheses, because then invocations of that method would look like a field selection.
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?
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.
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.
object HelloWorld {
case class Text(content: String)
case class Prefix(text: String)
implicit def String2Text(content: String)(implicit prefix: Prefix) = {
Text(prefix.text + " " + content)
}
def printText(text: Text): Unit = {
println(text.content)
}
def main(args: Array[String]): Unit = {
printText("World!")
}
// Best to hide this line somewhere below a pile of completely unrelated code.
// Better yet, import its package from another distant place.
implicit val prefixLOL = Prefix("Hello")
}
In scala implicit works as:
Converter
Parameter value injector
Extension method
There are some uses 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
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!
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
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))
}
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
Why and when you should mark the request parameter as implicit:
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:
def bindFromRequest()(implicit request: play.api.mvc.Request[_]): Form[T] = { ... }
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 as implicit.
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".
myForm.bindFromRequest()
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):
myForm.bindFromRequest()(request)
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 request implicit always. That way you can just write beautiful terse code.
Also, in the above case there should be only one implicit function whose type is double => Int. Otherwise, the compiler gets confused and won't compile properly.
//this won't compile
implicit def doubleToInt(d: Double) = d.toInt
implicit def doubleToIntSecond(d: Double) = d.toInt
val x: Int = 42.0
I had the exact same question as you had and I think I should share how I started to understand it by a few really simple examples (note that it only covers the common use cases).
There are two common use cases in Scala using implicit.
Using it on a variable
Using it on a function
Examples are as follows
Using it on a variable. As you can see, if the implicit keyword is used in the last parameter list, then the closest variable will be used.
// Here I define a class and initiated an instance of this class
case class Person(val name: String)
val charles: Person = Person("Charles")
// Here I define a function
def greeting(words: String)(implicit person: Person) = person match {
case Person(name: String) if name != "" => s"$name, $words"
case _ => "$words"
}
greeting("Good morning") // Charles, Good moring
val charles: Person = Person("")
greeting("Good morning") // Good moring
Using it on a function. As you can see, if the implicit is used on the function, then the closest type conversion method will be used.
val num = 10 // num: Int (of course)
// Here I define a implicit function
implicit def intToString(num: Int) = s"$num -- I am a String now!"
val num = 10 // num: Int (of course). Nothing happens yet.. Compiler believes you want 10 to be an Int
// Util...
val num: String = 10 // Compiler trust you first, and it thinks you have `implicitly` told it that you had a way to covert the type from Int to String, which the function `intToString` can do!
// So num is now actually "10 -- I am a String now!"
// console will print this -> val num: String = 10 -- I am a String now!
Hope this can help.
A very basic example of Implicits in scala.
Implicit parameters:
val value = 10
implicit val multiplier = 3
def multiply(implicit by: Int) = value * by
val result = multiply // implicit parameter wiil be passed here
println(result) // It will print 30 as a result
Note: Here multiplier will be implicitly passed into the function multiply. 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:
implicit def convert(a: Double): Int = a.toInt
val res = multiply(2.0) // Type conversions with implicit functions
println(res) // It will print 20 as a result
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 converts Int to Double (As function multiply accept Int parameter). If there is no implicit convert function then the compiler will not compile the code.
Given this definition:
class Foo(var x: String) {}
object Helper {
def model[T](get: ⇒ T, set: T ⇒ Unit) : Model[T] = new Model[T] {
override def getObject(): T = get
override def setObject(obj: T) { set(obj) }
}
}
I try to call model like this:
val f = new Foo("initial")
val stringModel = model(f.x, f.x = _)
But that doesn't work, the compiler gives me this, complaining about the underscore:
missing parameter type for expanded function ((x$1) => f.x = x$1)
If I change the definition of model to use two parameter lists like this:
def model[T](get: ⇒ T)(set: T ⇒ Unit) // rest is unchanged
Then I can call it like this:
model(f.x)(f.x = _)
Which I find nice and concise. I don't really mind doing it like this, though it makes method overloading harder. I would like to understand, however, why the second variant works and the first one doesn't?
The second variant works because Scala refines its types parameter-block by parameter-block. If you don't specify the type of your input parameter for the function, it's possible that it would change the type T that it has inferred based on the first parameter. If you push it to a separate parameter block, Scala's already decided what T must be by the time it hits that block, so it fills in the only possible value for the function argument type.