2
votes

I have the following piece of code.I have to confirm whether its the way how it works..Can anyone provide the explanation for this

object Implicits
{
  implicit class RichSeq[A](val xs:Seq[A])
  {
    def mapD[B](function:A => B):Seq[B] = xs.map(function)
  }
}

This is something like a abstraction over map that i can use with a sequence. So if I import this Implicits.RichSeq I can use the methods over any Seq[A] as this will convert Seq[A] into a RichSeq[A].

import Implicits.RichSeq._
val xs:Seq[Int] = Seq(22,33)
val output:Seq[Int] = xs.mapD(_+22)

I want to know how this works because when I use mapD on a type Seq[A] it will search for a implicit conversion from Seq[A] to RichSeq[A].Where does it find this implicit conversion as this is a implicit class?

Does it expand implicit class to something like:

implicit def RichSeq[A](val xs:Seq[A]) = new RichSeq(xs)

I think it might be doing this stuff inside.Does ne1 know about this?

2

2 Answers

5
votes

An implicit class is just a shorthand for

class Foo(a: A)
implicit def pimpMyA(a: A) = new Foo(a)

You can annotate a class as implicit if its constructor takes exactly one non-implicit parameter.

Here's the relevant doc where you can read more about it: http://docs.scala-lang.org/overviews/core/implicit-classes.html


In your specific example, it means that any Seq[A] can be implicitly lifted into a RichSeq[A].

The compiler will find the implicit because you imported it, so it's available in the scope.

You can see the actual java output of this code

val x = Seq(1, 2, 3)
x.mapD(_ + 22)

by using the scala REPL with the option -Xprint:typer. Here's the relevant bit of the output

$line3.$read.$iw.$iw.Implicits.RichSeq[Int]($line3.$read.$iw.$iw.x).mapD[Int](((x$1: Int) => x$1.+(22)));

which after some polishing is equivalent to

Implicits.RichSeq(x).mapD(x$1 => x$1 + 22)

As a side note, you just have to import Implicits._. For the exact implicit resolutions rules, you can refer to Where does Scala look for implicits?

2
votes

You only need to import

import Implicits._

It will inject the implicits into your scope.

I can confirm that Scala is creating a new RichSeq with your current Seq. If you want to try behavior like those, write something like that :

object Implicits {
  implicit class RichSeq[A](val xs:Seq[A]) {
    println("fuu") // print "fuu" when RichSeq is created 
    def mapD[B](function:A => B):Seq[B] = xs.map(function)
  }
}