Cosa significa l’operatore `# in Scala?

Vedo questo codice in questo blog: programmazione a livello di codice in 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’è un operatore # nel codice R#X[R#Next] che non ho mai visto. Dal momento che è difficile ricercarlo (ignorato dai motori di ricerca), chi può dirmi cosa significa?

Per spiegarlo, dobbiamo prima spiegare le classi nidificate in Scala. Considera questo semplice esempio:

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

Ora proviamo qualcosa con questo:

 scala> val a1 = new A a1: A = A@2fa8ecf4 scala> val a2 = new A a2: A = A@4bed4c8 scala> a2.f(new a1.B) :11: error: type mismatch; found : a1.B required: a2.B a2.f(new a1.B) ^ 

Quando dichiari una class all’interno di un’altra class in Scala, stai dicendo che ogni istanza di quella class ha una tale sottoclass. In altre parole, non esiste una class AB , ma ci sono classi a1.B e a2.B e sono classi diverse , come ci dice il messaggio di errore sopra.

Se non l’hai capito, cerca i tipi dipendenti dal percorso.

Ora, # rende ansible fare riferimento a tali classi annidate senza limitarlo a una particolare istanza. In altre parole, non c’è AB , ma c’è A#B , che significa una class nidificata in B di qualsiasi istanza di A

Possiamo vedere questo in azione cambiando il codice qui sopra:

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

E provandolo:

 scala> val a1 = new A a1: A = A@1497b7b1 scala> val a2 = new A a2: A = A@2607c28c scala> a2.f(new a1.B) :11: error: type mismatch; found : a1.B required: a2.B a2.f(new a1.B) ^ scala> a2.g(new a1.B) Got a B. 

È noto come tipo proiezione e viene utilizzato per accedere ai membri del tipo.

 scala> trait R { | type A = Int | } defined trait R scala> val x = null.asInstanceOf[R#A] x: Int = 0 

Fondamentalmente, è un modo di riferirsi a classi all’interno di altre classi.

http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (cerca “pound”)

Ecco una risorsa per la ricerca su “operatori simbolici” (che sono davvero metodi), ma non ho capito come sfuggire “#” per cercare su in scalax)

http://www.artima.com/pins1ed/book-index.html#indexanchor