Что означает оператор # в Scala?
Я вижу этот код в этом блоге: Программирование на уровне типов в Scala:
// define the abstract types and bounds
trait Recurse {
type Next <: Recurse
// this is the recursive function definition
type X[R <: Recurse] <: Int
}
// implementation
trait RecurseA extends Recurse {
type Next = RecurseA
// this is the implementation
type X[R <: Recurse] = R#X[R#Next]
}
object Recurse {
// infinite loop
type C = RecurseA#X[RecurseA]
}
Есть оператор #
в коде R#X[R#Next]
которого я никогда не видел. Так как это трудно найти (игнорируется поисковыми системами), кто может сказать мне, что это значит?
4 ответа
Чтобы объяснить это, мы сначала должны объяснить вложенные классы в Scala. Рассмотрим этот простой пример:
class A {
class B
def f(b: B) = println("Got my B!")
}
Теперь давайте попробуем что-нибудь с этим:
scala> val a1 = new A
a1: A = A@2fa8ecf4
scala> val a2 = new A
a2: A = A@4bed4c8
scala> a2.f(new a1.B)
<console>:11: error: type mismatch;
found : a1.B
required: a2.B
a2.f(new a1.B)
^
Когда вы объявляете класс внутри другого класса в Scala, вы говорите, что у каждого экземпляра этого класса есть такой подкласс. Другими словами, нет A.B
класс, но есть a1.B
а также a2.B
классы, и это разные классы, как сказано выше в сообщении об ошибке.
Если вы этого не поняли, ищите зависимые от пути типы.
Сейчас, #
позволяет вам ссылаться на такие вложенные классы, не ограничивая его конкретным экземпляром. Другими словами, нет A.B
, но есть A#B
, что означает B
вложенный класс любого экземпляра A
,
Мы можем увидеть это в работе, изменив код выше:
class A {
class B
def f(b: B) = println("Got my B!")
def g(b: A#B) = println("Got a B.")
}
И попробовать это:
scala> val a1 = new A
a1: A = A@1497b7b1
scala> val a2 = new A
a2: A = A@2607c28c
scala> a2.f(new a1.B)
<console>:11: error: type mismatch;
found : a1.B
required: a2.B
a2.f(new a1.B)
^
scala> a2.g(new a1.B)
Got a B.
Он известен как проекция типа и используется для доступа к членам типа.
scala> trait R {
| type A = Int
| }
defined trait R
scala> val x = null.asInstanceOf[R#A]
x: Int = 0
По сути, это способ ссылки на классы внутри других классов.
http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (поиск "фунт")
Вот ресурс для поиска по "символическим операторам" (которые на самом деле являются методами), но я не понял, как избежать "#" для поиска в scalex)