Apa arti operator `#` di Scala?

131

Saya melihat kode ini di blog ini: Pemrograman Tipe-Level di 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]
}

Ada operator #dalam kode R#X[R#Next]yang belum pernah saya lihat. Karena sulit untuk mencarinya (diabaikan oleh mesin pencari), siapa yang dapat memberi tahu saya apa artinya?

Jalan bebas
sumber
1
"tanda pon" kadang-kadang disebut sebagai "octathrop" (pencarian google membawa saya ke halaman ini).
philwalk
3
Jadikan octothorpe atau octothorp
smparkes
Bagaimana dengan operator lain seperti # + dan # - (lihat github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/… )? Apakah ada daftar lengkap?
Markus Barthlen

Jawaban:

240

Untuk menjelaskannya, pertama-tama kita harus menjelaskan kelas bersarang di Scala. Pertimbangkan contoh sederhana ini:

class A {
  class B

  def f(b: B) = println("Got my B!")
}

Sekarang mari kita coba sesuatu dengannya:

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

Ketika Anda mendeklarasikan kelas di dalam kelas lain di Scala, Anda mengatakan bahwa setiap instance dari kelas itu memiliki subclass seperti itu. Dengan kata lain, tidak ada A.Bkelas, tetapi ada a1.Bdan a2.Bkelas, dan mereka adalah kelas yang berbeda , seperti pesan kesalahan memberitahu kita di atas.

Jika Anda tidak mengerti itu, cari tipe jalan yang tergantung.

Sekarang, #buatlah kemungkinan bagi Anda untuk merujuk ke kelas bertingkat seperti itu tanpa membatasi ke instance tertentu. Dengan kata lain, tidak ada A.B, tapi ada A#B, yang berarti Bkelas bersarang dari setiap contoh A.

Kita dapat melihat ini sedang bekerja dengan mengubah kode di atas:

class A {
  class B

  def f(b: B) = println("Got my B!")
  def g(b: A#B) = println("Got a B.")
}

Dan mencobanya:

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.
Daniel C. Sobral
sumber
Contoh yang bagus. Saya benar-benar menerima bahwa itu bekerja seperti itu tetapi sulit untuk memahami ini: scala> classOf [A # B] res7: Kelas [A # B] = kelas A $ B scala> classOf [aB] res8: Kelas [aB] = kelas A $ B. yang artinya, sebenarnya mereka memiliki tipe yang sama?
Chiron
2
Nilai-nilai mereka memiliki representasi string yang sama - dan mereka bahkan mungkin sama. Classadalah representasi runtime dari kelas Java, dan terbatas bahkan di Jawa. Misalnya, List<String>dan List<Integer>memiliki runtime yang sama Class. Jika Classtidak cukup kaya untuk mewakili tipe Java , hampir tidak ada gunanya saat mewakili tipe Scala . Sekali lagi, res7: Class[A#B] = class A$Bkiri tanda sama dengan adalah tipe, kanan dari sama dengan jika nilai yang merupakan representasi runtime Java dari suatu kelas.
Daniel C. Sobral
13

Ini dikenal sebagai tipe proyeksi, dan digunakan untuk mengakses anggota tipe.

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

scala> val x = null.asInstanceOf[R#A]
x: Int = 0
missingfaktor
sumber
6
Ini bukan jawaban. Ini pada dasarnya menunjukkan kode yang sama dengan pertanyaan, hanya sedikit disingkat. Apa, misalnya notasi perbedaan ke titik? Di mana saya akan menggunakan # ini dalam kode nyata?
notan3xit
2
@ notan3xit mungkin itu bukan jawaban untuk apa yang ingin Anda tanyakan. Tetapi yang Anda tanyakan adalah "... yang belum pernah saya lihat. Karena sulit untuk mencarinya (diabaikan oleh mesin pencari), siapa yang dapat memberi tahu saya apa artinya?"
nafg