Добавить метод в библиотеку с неявным scala - PullRequest
1 голос
/ 26 февраля 2012

Я хочу добавить новую функцию «extra» в библиотечный класс (например, «orig»).

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

Если я прокомментирую 1-е неявное преобразование, я получу ошибку. Я прочитал спецификацию Scala и подозреваю, что есть два места для неявного поиска:

  1. сопутствующий объект аргумента

  2. объект, содержащий аргумент

Какие-нибудь советы? К сожалению, большая часть официальной документации о неявном не очень полезна, и поиск переполнения стека тоже.

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

Я читаю Где Scala ищет следствия? , очень полезно. И найдите мой случай - Неявная область действия типа аргумента

Пример, который сработал:

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)
}

Измените это немного, просто имя функции (что я на самом деле хочу) и :-( упс

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 версия 2.9.1.r0-b20120114153402 (64-разрядная виртуальная машина OpenJDK, Java 1.6.0_22).

Это немного сбивает с толку. Я пытался смешать

7,3 Просмотров

  1. В выборе e.m с e типа T, если селектор m не обозначает член T. В этом случае ищется представление v, которое применимо к e и чей результат содержит член с именем m. Поиск продолжается как в случае неявного параметры, где неявная область видимости - та из T. Если такой вид найден, выбор e.m преобразуется в v (e) .m.
  2. В выборке e.m (args) с e типа T, если селектор m обозначает некоторую память ber (s) из T, но ни один из этих членов не применим к аргументам args. В в этом случае ищется представление v, которое применимо к e и результат которого использует метод m, который применим к аргументам. Поиск продолжается как в случай неявных параметров, где неявная область видимости равна

ИМХО это не возможно

Спасибо

Ответы [ 2 ]

2 голосов
/ 26 февраля 2012

Scala применяет неявные преобразования, которые видны в той же области, поэтому вы можете просто добавить строку

import rich.orig2rich

или

import rich._

Этот код будет работать

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)
0 голосов
/ 26 февраля 2012

Возможно, проблема заключается в последовательности загрузки orig и rich или rich и implicit def.

Кстати, следующий код работает нормально, я определил origсначала rich и, наконец, implicit преобразование в сутенер 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()))
...