Question

I'm reading the book Scala in Depth, chapter 5 about implicits. The author says this on page 102:

The implicit scope used for implicit views is the same as for implicit parameters. But when the compiler is looking for type associations, it uses the type it's attempting to convert from [my emphasis], not the type it's attempting to convert to.

And yet, a few pages later he shows an example, with a complexmath.ComplexNumber class. You import i, which is a ComplexNumber, and call it's * method, which takes a ComplexNumber argument.

import complexmath.i
i * 1.0

To convert 1.0 into a ComplexNumber, this finds an implicit conversion that was defined like so:

package object complexmath {
  implicit def realToComplex(r: Double) = new ComplexNumber(r, 0)
  val i = ComplexNumber(0, 1)    

But that contradicts the first statement, no? It needed to find Double => ComplexNumber. Why did it look in the complexmath package, which is part of the implicit scope for ComplexNumber but not for Double?

Was it helpful?

Solution 4

Either source or target works:

object Foo {
  implicit def bar(b: Bar): Foo = new Foo {}
  implicit def foo(f: Foo): Bar = new Bar {}
}
trait Foo
trait Bar

implicitly[Foo => Bar]  // ok
implicitly[Bar => Foo]  // ok

val b = new Bar {}
val bf: Foo = b  // ok
val f = new Foo {}
val fb: Bar = f  // ok

So I think that sentence is wrong (?)

OTHER TIPS

The spec says about views:

the implicit scope is the one of T => pt.

i.e., Function[T, pt], so implicit scope includes the classes associated with both T and pt, the source and target of the conversion.

scala> :pa
// Entering paste mode (ctrl-D to finish)

class B
class A
object A { implicit def x(a: A): B = new B }

// Exiting paste mode, now interpreting.

warning: there were 1 feature warning(s); re-run with -feature for details
defined class B
defined class A
defined object A

scala> val b: B = new A
b: B = B@63b41a65

scala> def f(b: B) = 3 ; def g = f(new A)
f: (b: B)Int
g: Int

scala> :pa
// Entering paste mode (ctrl-D to finish)

class A
class B
object B { implicit def x(a: A): B = new B }

// Exiting paste mode, now interpreting.

scala> val b: B = new A
b: B = B@6ba3b481

I think you are misunderstanding his text.

The compiler will look for the implicit conversion in all available scopes until it finds a suitable one.

In the example you specified it'll find one being provided by the complexmath package.

However, is the definition of 'suitable one' that we are interested here. In case of implicit conversions, the compiler will look for a conversion from *Double* to the expected type ComplexNumber.

In other words, it'll inspect all conversions from *Double* until it finds one that can convert a Double to the target type.

Josh, the author, is not saying that the compiler needs a conversion defined in an object associated with the Double object. The conversion can be defined everywhere.

In this particular case, the conversion is defined in the package object associated with the ComplexNumber object. And that's normal, is the ComplexNumber object that 'wants' to be compatible with Double.

And since the usage implies the import of ComplexNumber and therefore the import of package 'complexmath', the conversion will be always in scope.

So this is more about what the compiler already *know*s about an expression.

You have in the example:

import complexmath.i
i * 1.0

The compiler looks at this to start with:

1) I have a type for i, it is Complex 2) I have a method on i called *, it takes an argument of type Complex 3) You passed me an Int, but I need a Complex. let's see if i have an implicit which gives me that.

This example works because the * method is defined on Complex.

Hope that helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top