funciones - recorrer lista scala
¿Qué significa el operador `#` en Scala? (4)
Veo este código en este blog: Programación a nivel de tipo en 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]
}
Hay un operador #
en el código R#X[R#Next]
que nunca he visto. Como es difícil buscarlo (ignorado por los motores de búsqueda), ¿quién puede decirme qué significa?
Aquí hay un recurso para buscar en "operadores simbólicos" (que en realidad son métodos), pero no he descubierto cómo escapar "#" para buscar en scalex)
Básicamente, es una forma de referirse a clases dentro de otras clases.
http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (busque "libra")
Para explicarlo, primero tenemos que explicar las clases anidadas en Scala. Considera este simple ejemplo:
class A {
class B
def f(b: B) = println("Got my B!")
}
Ahora intentemos algo con esto:
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)
^
Cuando declaras una clase dentro de otra clase en Scala, estás diciendo que cada instancia de esa clase tiene dicha subclase. En otras palabras, no hay clases AB
, pero hay clases a1.B
y a2.B
, y son clases diferentes , como nos dice el mensaje de error anterior.
Si no lo entendió, busque los tipos que dependen de la ruta.
Ahora, #
hace posible que se refiera a tales clases anidadas sin restringirlo a una instancia particular. En otras palabras, no hay AB
, pero hay A#B
, lo que significa una clase anidada B
de cualquier instancia de A
Podemos ver esto en el trabajo cambiando el código anterior:
class A {
class B
def f(b: B) = println("Got my B!")
def g(b: A#B) = println("Got a B.")
}
Y probándolo:
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.
Se conoce como proyección de tipo, y se usa para acceder a miembros de tipo.
scala> trait R {
| type A = Int
| }
defined trait R
scala> val x = null.asInstanceOf[R#A]
x: Int = 0