Toán tử `#` có nghĩa gì trong Scala?


131

Tôi thấy mã này trong blog này: Lập trình cấp độ trong 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]
}

Có một toán tử #trong mã R#X[R#Next]mà tôi chưa từng thấy. Vì việc tìm kiếm nó rất khó khăn (bị các công cụ tìm kiếm bỏ qua), ai có thể cho tôi biết ý nghĩa của nó là gì?


1
"dấu thăng" đôi khi được gọi là "octathrop" (tìm kiếm google đó đã đưa tôi đến trang này).
philwalk


Whatabout các nhà khai thác khác như # + và # - (xem github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/ tựa )? Có một danh sách toàn diện?
Markus Barthlen

Câu trả lời:


240

Để giải thích nó, trước tiên chúng ta phải giải thích các lớp lồng nhau trong Scala. Hãy xem xét ví dụ đơn giản này:

class A {
  class B

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

Bây giờ hãy thử một cái gì đó với nó:

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

Khi bạn khai báo một lớp bên trong một lớp khác trong Scala, bạn đang nói rằng mỗi phiên bản của lớp đó có một lớp con như vậy. Nói cách khác, không có A.Blớp, nhưng có a1.Ba2.Bcác lớp, và chúng là các lớp khác nhau , vì thông báo lỗi đang nói với chúng tôi ở trên.

Nếu bạn không hiểu điều đó, hãy tìm các loại phụ thuộc đường dẫn.

Bây giờ, #làm cho bạn có thể tham khảo các lớp lồng nhau như vậy mà không giới hạn nó trong một trường hợp cụ thể. Nói cách khác, không có A.B, nhưng có A#B, có nghĩa là một Blớp lồng của bất kỳ trường hợp nàoA .

Chúng ta có thể thấy điều này trong công việc bằng cách thay đổi mã ở trên:

class A {
  class B

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

Và thử nó:

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.

Ví dụ tuyệt vời. Tôi hoàn toàn chấp nhận rằng nó hoạt động theo cách đó nhưng khó hiểu điều này: scala> classOf [A # B] res7: Class [A # B] = class A $ B scala> classOf [aB] res8: Class [aB] = class A $ B. có nghĩa là, họ có cùng loại thực sự?
Chiron

2
Các giá trị của chúng có cùng biểu diễn chuỗi - và thậm chí chúng có thể bằng nhau. Classlà một đại diện thời gian chạy của các lớp Java và nó bị giới hạn ngay cả trong Java. Ví dụ, List<String>List<Integer>có cùng thời gian chạy Class. Nếu Classkhông đủ phong phú để đại diện cho các loại Java , thì nó gần như vô dụng khi đại diện cho các loại Scala . Một lần nữa, res7: Class[A#B] = class A$Bbên trái của dấu bằng là một loại, bên phải của loại bằng nếu một giá trị là biểu diễn thời gian chạy Java của một lớp.
Daniel C. Sobral

13

Nó được gọi là phép chiếu kiểu và được sử dụng để truy cập các thành viên kiểu.

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

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

6
Đây là một câu trả lời không. Về cơ bản, nó hiển thị cùng mã với câu hỏi, chỉ cần rút ngắn một chút. Ví dụ, sự khác biệt với ký hiệu điểm là gì? Tôi sẽ sử dụng # này trong mã thực ở đâu?
notan3xit

2
@ notan3xit có thể đó không phải là câu trả lời cho những gì bạn muốn hỏi. Nhưng điều bạn hỏi là "... điều mà tôi chưa từng thấy. Vì rất khó tìm kiếm nó (bị các công cụ tìm kiếm bỏ qua), ai có thể cho tôi biết ý nghĩa của nó là gì?"
nafg


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.