Що означає оператор `#` у Scala?


131

Я бачу цей код у цьому блозі: Програмування на рівні в 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]якого я ніколи не бачив. Оскільки його важко шукати (ігнорувати пошукові системи), хто може мені сказати, що це означає?


1
"знак фунта" іноді називають "октатропом" (цей пошук в Google завів мене на цю сторінку).
philwalk


Що щодо інших операторів, таких як # + і # - (див. Github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/… )? Чи є вичерпний перелік?
Маркус Бартлен

Відповіді:


240

Щоб пояснити це, спершу треба пояснити вкладені класи у 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> classOf [A # B] res7: Class [A # B] = class A $ B scala> classOf [aB] res8: Class [aB] = class A $ B. це означає, що вони мають один і той же тип?
Хірон

2
Їх значення мають однакове струнне представлення - і вони можуть бути навіть рівними. Class- це представлення класів Java, і воно обмежене навіть у Java. Наприклад, List<String>і List<Integer>мають однаковий час виконання Class. Якщо Classвін недостатньо багатий для представлення типів Java , це майже марно при представленні типів Scala . Знову, res7: Class[A#B] = class A$Bліворуч від знака рівності - це тип, праворуч тип дорівнює, якщо значення, яке є представленням Java часу виконання класу.
Даніель К. Собрал

13

Він відомий як проекція типу і використовується для доступу до типів членів.

scala> trait R {
     |   type A = Int
     | }
defined trait R

scala> val x = null.asInstanceOf[R#A]
x: Int = 0

6
Це невідповідь. В основному він показує той самий код, що і питання, лише трохи скорочений. Яка, наприклад, різниця в нотації точок? Де я можу використовувати цей # у реальному коді?
notan3xit

2
@ notan3xit, можливо, це невідповідь на те, що ти мав намір запитати. Але те, що ви запитали, це "... чого я ніколи не бачив. Оскільки його важко шукати (ігнорувати пошукові системи), хто може мені сказати, що це означає?"
нафг


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.