Je vois ce code dans ce blog: Programmation au niveau du type dans 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]
}
Il y a un opérateur #
dans le code R#X[R#Next]
que je n'ai jamais vu. Puisqu'il est difficile de le rechercher (ignoré par les moteurs de recherche), qui peut me dire ce que cela signifie?
Pour l'expliquer, nous devons d'abord expliquer les classes imbriquées dans Scala. Considérez cet exemple simple:
class A {
class B
def f(b: B) = println("Got my B!")
}
Essayons maintenant quelque chose avec:
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)
^
Lorsque vous déclarez une classe à l'intérieur d'une autre classe dans Scala, vous dites que chaque instance de cette classe a une telle sous-classe. En d'autres termes, il n'y a pas de A.B
classe, mais il y a a1.B
et a2.B
classes, et ce sont différentes classes, comme le message d'erreur nous le dit plus haut.
Si vous ne comprenez pas cela, recherchez les types dépendants du chemin.
Maintenant, #
vous permet de vous référer à de telles classes imbriquées sans la restreindre à une instance particulière. En d'autres termes, il n'y a pas de A.B
, mais il y'à A#B
, ce qui signifie une classe imbriquée B
de toute instance de A
.
Nous pouvons voir cela au travail en changeant le code ci-dessus:
class A {
class B
def f(b: B) = println("Got my B!")
def g(b: A#B) = println("Got a B.")
}
Et l'essayer:
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.
Il est connu sous le nom de projection de type et est utilisé pour accéder aux membres de type.
scala> trait R {
| type A = Int
| }
defined trait R
scala> val x = null.asInstanceOf[R#A]
x: Int = 0
Fondamentalement, c'est une façon de se référer à des classes dans d'autres classes.
http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (recherche de "livre")
Voici une ressource pour rechercher des "opérateurs symboliques" (qui sont vraiment des méthodes), mais je n'ai pas compris comment échapper à "#" pour rechercher dans scalex)