2

I want to add new function "extra" to library class ("orig" for example).

orig.extra(rich.Arg()) // <- like this

If I comment 1st implicit conversion than I get error. I read Scala specification, and suspect that there are two places for implicit lookup:

  1. companion object of argument

  2. object that holds argument

Any tips? Unfortunately most official documentation about implicit is not very helpful and stack overflow search too.

scala> object container {
 |   //implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }
 |   object rich {
 |     implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
 |     case class Arg(val some: String = "some")
 |     object Arg {
 |       implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
 |     }
 |   }
 |   object orig {
 |     def standard(s: String) = "standard"
 |   }
 |   orig.extra(rich.Arg())
 | }
<console>:35: error: value extra is not a member of object container.orig
     orig.extra(rich.Arg())

EDIT

I read Where does Scala look for implicits?, very useful. And find my case - Implicit scope of an argument's type

Example that worked:

object container {
class A(val n: Int) {
  def +(other: A) = new A(n + other.n)
}
object A {
  implicit def fromInt(n: Int) = new A(n)
}

// This becomes possible:
1 + new A(1)
// because it is converted into this:
A.fromInt(1) + new A(1)
}

Change it a bit, just function name (what I actually want), and :-( oops

object container {
class A(val n: Int) {
  def hello(other: A) = new A(n + other.n)
}
object A {
  implicit def fromInt(n: Int) = new A(n)
}

// This becomes possible:
1.hello(new A(1))
// because it is converted into this:
A.fromInt(1).hello(new A(1))
}

<console>:16: error: value hello is not a member of Int
       1.hello(new A(1))

Scala version 2.9.1.r0-b20120114153402 (OpenJDK 64-Bit Server VM, Java 1.6.0_22).

It is a bit confusing. I tried to mix

7.3 Views

  1. In a selection e.m with e of type T , if the selector m does not denote a member of T . In this case, a view v is searched which is applicable to e and whose result contains a member named m. The search proceeds as in the case of implicit parameters, where the implicit scope is the one of T . If such a view is found, the selection e.m is converted to v (e ).m.
  2. In a selection e.m(args) with e of type T , if the selector m denotes some mem- ber(s) of T , but none of these members is applicable to the arguments args. In this case a view v is searched which is applicable to e and whose result con- tains a method m which is applicable to args. The search proceeds as in the case of implicit parameters, where the implicit scope is the one of

IMHO it is not possible

Thank you

Community
  • 1
  • 1
Ezhik
  • 876
  • 6
  • 23

2 Answers2

3

scala is applying implicit conversions that are visible in the same scope, so you can just add line

import rich.orig2rich

or

import rich._

This code will work

object container {

  //implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }
  object rich {
    implicit def orig2rich(o: orig.type) = new {
      def extra(a: Arg) = "extra"
    }

    case class Arg(val some: String = "some")

    object Arg {
      implicit def orig2rich(o: orig.type) = new {
        def extra(a: Arg) = "extra"
      }
    }

  }

  object orig {
    def standard(s: String) = "standard"
  }

  import rich.orig2rich

  def test = orig.extra(rich.Arg())
}

println(container.test)
Odomontois
  • 15,918
  • 2
  • 36
  • 71
0

The problem might be the loading sequence, of orig and rich, or the rich and the implicit def.

Btw, the following code works fine, I defined orig first than rich and finally applied the implicit conversion to pimp orig

object container {
    object orig {
            def standard(s:String) = "standard"
    }

    object rich {
            case class Arg(val some: String = "some")

            object Arg {
                    implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
            }
    }

    implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }

    orig.extra(rich.Arg())
}

println(container.orig.extra(container.rich.Arg()))
Andy Petrella
  • 4,345
  • 26
  • 29