136 votes

Que signifie l'opérateur `#` en Scala ?

Je vois ce code dans ce blog : Programmation par niveau de type 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]
}

Il existe 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 votes

Le "signe dièse" est parfois appelé "octathrop" (cette recherche google m'a amené à cette page).

3 votes

0 votes

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 exhaustive ?

253voto

Daniel C. Sobral Points 159554

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

class A {
  class B

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

Maintenant, essayons quelque chose avec ça :

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 en Scala, vous dites que chaque cas de cette classe a une telle sous-classe. En d'autres termes, il n'y a pas de A.B mais il y a a1.B y a2.B et ils sont différents comme l'indique le message d'erreur ci-dessus.

Si vous n'avez pas compris cela, consultez les types dépendants du chemin.

Maintenant, # vous permet de faire référence à ces classes imbriquées sans vous limiter à une instance particulière. En d'autres termes, il n'y a pas de A.B mais il y a A#B ce qui signifie qu'un B classe imbriquée de tout exemple de A .

Nous pouvons voir cela en action 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.

0 votes

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

2 votes

Leurs valeurs ont la même représentation de chaîne de caractères - et elles peuvent même être égales. Class est une représentation runtime des classes Java, et elle est limitée même en Java. Par exemple, List<String> y List<Integer> ont le même temps d'exécution Class . Si Class n'est pas assez riche pour représenter Java il est presque inutile lorsqu'il s'agit de représenter Scala types. Encore une fois, res7: Class[A#B] = class A$B à gauche du signe égal est un type, à droite du type égal est une valeur qui est le Java temps de fonctionnement représentation d'une classe.

17voto

missingfaktor Points 44003

C'est ce qu'on appelle la projection de type, et elle est utilisée pour accéder aux membres du type.

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

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

7 votes

C'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 ponctuelle ? Où pourrais-je utiliser ce # dans du code réel ?

3 votes

@notan3xit peut-être que c'est une non-réponse à ce que vous vouliez demander. Mais ce que vous avez demandé est " ... 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 ?"

8voto

moveaway00 Points 457

Il s'agit essentiellement d'un moyen de faire référence à des classes au sein d'autres classes.

http://jim-mcbeath.blogspot.com/2008/09/scala-syntax-primer.html (recherche pour "pound")

2voto

Gene T Points 4308

Voici une ressource pour faire des recherches sur les "opérateurs symboliques" (qui sont en fait des méthodes), mais je n'ai pas encore trouvé comment échapper à "#" pour faire une recherche en scalex)

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X