ตัวดำเนินการ `# 'หมายถึงอะไรใน Scala?


131

ฉันเห็นรหัสนี้ในบล็อกนี้: Type-Level Programming ใน 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
"เครื่องหมายปอนด์" บางครั้งเรียกว่า "octathrop" (ซึ่งการค้นหาโดย Google ทำให้ฉันมาที่หน้านี้)
philwalk


เกี่ยวกับตัวดำเนินการอื่น ๆ เช่น # + และ # - (ดูgithub.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/… ) มีรายการที่ครอบคลุมหรือไม่?
Markus Barthlen

คำตอบ:


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. ซึ่งหมายความว่ามีประเภทเดียวกันจริงหรือ?
Chiron

2
ค่าของพวกเขามีการแสดงสตริงเดียวกัน - และอาจเท่ากันด้วยซ้ำ Classคือการแสดงรันไทม์ของคลาส Java และ จำกัด แม้กระทั่งใน Java ยกตัวอย่างเช่นList<String>และมีรันไทม์เดียวกันList<Integer> ClassหากClassไม่สมบูรณ์เพียงพอที่จะแสดงประเภทJavaก็แทบจะไม่มีประโยชน์เมื่อแสดงประเภทScala อีกครั้งres7: Class[A#B] = class A$Bทางซ้ายของเครื่องหมายเท่ากับคือประเภททางขวาของประเภทเท่ากับถ้าค่าซึ่งเป็นตัวแทนรันไทม์ Java ของคลาส
Daniel C. Sobral

13

เรียกว่า type projection และใช้เพื่อเข้าถึงสมาชิกประเภท

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

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

6
นี่คือคำตอบที่ไม่ใช่ โดยทั่วไปจะแสดงรหัสเดียวกับคำถามสั้นลงเล็กน้อย ตัวอย่างเช่นความแตกต่างของสัญกรณ์ชี้คืออะไร? ฉันจะใช้ # นี้ในรหัสจริงได้ที่ไหน
notan3xit

2
@ notan3xit อาจจะไม่ใช่คำตอบสำหรับสิ่งที่คุณต้องการถาม แต่สิ่งที่คุณถามคือ "... ซึ่งฉันไม่เคยเห็นมาก่อนเนื่องจากมันยากที่จะค้นหา (ไม่สนใจโดยเครื่องมือค้นหา) ใครสามารถบอกฉันได้ว่ามันหมายถึงอะไร"
nafg


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.