If I define a print function that only takes numbers as:
def print[T <% Number](value:T) {}
print: [T](value: T)(implicit evidence$1: (T) => java.lang.Number)Unit
I can call the above with:
print(5)
print(5.5)
print(6L)
But not with a String:
print("aaa")
<console>:7: error: could not find implicit value for evidence parameter of type (java.lang.String) => java.lang.Number
print("aaa")
This is expected.
But if I define the print function as:
def print2[T <% Number]: T => Unit = value => { }
print2: [T](implicit evidence$1: (T) => java.lang.Number)(T) => Unit
Notice how the implicit parameter is the first parameter instead of the last.
If I try to manually define the above function:
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
<console>:1: error: '=' expected but '(' found.
def print3[T](implicit f: (T) => java.lang.Number)(value:T):Unit = { }
Basically the above is not a valid function definition but the compiler creates it when I previously defined print2.
When I call print2 with an Int:
print2(5)
<console>:7: error: type mismatch;
found : Int(5)
required: (?) => java.lang.Number
print2(5)
if I parameterize it:
print2[Int](5)
<console>:7: error: type mismatch;
found : Int(5)
required: (Int) => java.lang.Number
print2[Int](5)
It looks like it can't find the implicit conversion from scala.Int => java.lang.Integer.
How can I redefine print such that it returns functions and also accesses implicits in the correct way?
The implicit parameter in Java is the object that the method belongs to. It's passed by specifying the reference or variable of the object before the name of the method. An implicit parameter is opposite to an explicit parameter, which is passed when specifying the parameter in the parenthesis of a method call.
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.
A method or constructor can have only one implicit parameter list, and it must be the last parameter list given.
The implicit system in Scala allows the compiler to adjust code using a well-defined lookup mechanism. A programmer in Scala can leave out information that the compiler will attempt to infer at compile time. The Scala compiler can infer one of two situations: A method call or constructor with a missing parameter.
The problem here is that you are passing 5 as the implicit parameter.
Now that I'm on a computer, a few corrections:
def print[T <% Number](value:T) {}
You call this a function, but it is a method.
def print2[T <% Number]: T => Unit = value => { }
Again, you call this a function. Actually, it is a method which returns a function. The method receives one type parameter, T
, and one implicit parameter.
print2(5)
So, here, you call the method print2
passing 5
as its implicit parameter. The type T
hasn't been infered yet because it is first trying to conform 5
to the expected type T => Number
. However, since 5
doesn't conform to Function1[T, Number]
, it fails without even inferring T
.
There are many ways to call print2
. For example:
print2(implicitly[Int => Number])
print2[Int]
(print2: Int => Unit)
val f: Int => Unit = print2
However, to call the function that is returned by print2
, you have to avoid making (5)
look like the implicit parameter to the method print2
. There's actually only one case above that needs something different:
print2(implicitly[Int => Number])(5)
print2[Int].apply(5)
(print2: Int => Unit)(5)
val f: Int => Unit = print2; f(5)
Now, most of these examples have explicit, instead of inferred, type parameters. Let's consider what would happen in its absence:
print2.apply(5)
Because no parameter was passed to print2
, it selects the most specific type that conforms to the bounds of T
. Since T
has no bounds, Nothing
is chosen. It then tries to find an implicit Nothing => Unit
. Because there's no such implicit, it fails.
The parameter to the function that would be returned by print2
is never looked into to help type inference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With