Que signifie l'opérateur «#» dans Scala?


131

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. Comme il est difficile de le rechercher (ignoré par les moteurs de recherche), qui peut me dire ce que cela signifie?


1
le «signe dièse» est parfois appelé «octathrop» (cette recherche Google m'a amené à cette page).
philwalk


Qu'en est-il des autres opérateurs comme # + et # - (voir github.com/tpolecat/doobie/blob/series/0.4.x/yax/h2/src/main/… )? Existe-t-il une liste complète?
Markus Barthlen

Réponses:


240

Pour l'expliquer, nous devons d'abord expliquer les classes imbriquées dans Scala. Prenons cet exemple simple:

class A {
  class B

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

Maintenant, essayons 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 dans 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.Bclasse, mais il y a a1.Bet des a2.Bclasses, et ils sont différents des classes, comme le message d'erreur nous dit ci - dessus.

Si vous ne comprenez pas cela, recherchez les types dépendants du chemin.

Maintenant, #vous permet de faire référence à de telles classes imbriquées sans la limiter à une instance particulière. En d'autres termes, il n'y a pas A.B, mais il y a A#B, ce qui signifie une Bclasse imbriquée de n'importe quelle instance de A.

Nous pouvons voir cela dans le travail en modifiant 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.

Excellent exemple. J'accepte totalement que cela fonctionne de cette façon, mais difficile à comprendre: scala> classOf [A # B] res7: Class [A # B] = classe A $ B scala> classOf [aB] res8: Classe [aB] = classe A $ B. ce qui signifie qu'ils ont le même type en fait?
Chiron

2
Leurs valeurs ont la même représentation sous forme de chaîne - et elles peuvent même être égales. Classest une représentation d'exécution des classes Java, et elle est limitée même en Java. Par exemple, List<String>et List<Integer>ont le même runtime Class. Si ce Classn'est pas assez riche pour représenter les types Java , il est presque inutile lors de la représentation des types Scala . Là encore, à res7: Class[A#B] = class A$Bgauche du signe égal se trouve un type, à droite du type égal s'il s'agit d'une valeur qui est la représentation d' exécution Java d'une classe.
Daniel C.Sobral

13

Elle est connue sous le nom de projection de type et est utilisée 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

6
Ceci est une non-réponse. Il montre essentiellement le même code que la question, juste légèrement raccourci. Quelle est, par exemple, la différence avec la notation par points? Où utiliserais-je ce # dans du vrai code?
notan3xit

2
@ notan3xit c'est peut-être une non-réponse à ce que vous vouliez demander. Mais ce que vous avez demandé, c'est "... ce que je n'ai jamais vu. Comme il est difficile de le rechercher (ignoré par les moteurs de recherche), qui peut me dire ce que cela signifie?"
nafg


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.