28 votes

Est-il possible pour Scala d'avoir des génériques réifiés sans changer la JVM?

J'ai récemment commencé à apprendre Scala et j'ai été déçu (mais pas surpris) que leurs génériques soient également implémentés via l'effacement de type.

Ma question est la suivante: est-il possible pour Scala d'avoir des génériques réifiés, ou la JVM devrait-elle être modifiée d'une manière ou d'une autre? Si la JVM doit être changée, que faudrait-il exactement changer?

21voto

oxbow_lakes Points 70013

Non - il n'est pas possible pour Scala à exécuter en tant que Java-équivalent du bytecode si ce bytecode ne prend pas en charge réifiée génériques.

Lorsque vous demandez "qu'est-ce qui doit être changé?", la réponse est: le bytecode de la spécification. Actuellement, le bytecode n'autorise pas la paramétrées type d'une variable à définir. Il a été décidé que comme une modification du bytecode à l'appui de réifiée génériques permettrait de casser la compatibilité descendante, que les génériques devraient être mis en œuvre par le type d'effacement.

Pour contourner ce problème, la Scala a utilisé la puissance de ses implicit mécanisme pour définir un Manifest qui peut être importé dans toute l'étendue de découvrir des informations de type à l'exécution. Les manifestes sont expérimentales et principalement sans papiers, mais ils sont à venir dans le cadre de la bibliothèque dans la 2.8. Voici une autre bonne ressource sur Scala réifiée génériques / Manifests

5voto

Daniel C. Sobral Points 159554

Juste pour compléter oxbow_lakes, il y a une question sur Stack Overflow sur la façon de contourner l'effacement de type dans Scala .

3voto

Walter Chang Points 7041

"implicite Manifeste" est un compilateur Scala truc et il ne fait pas de génériques en Scala réifiée. Le compilateur Scala, quand il voit une fonction avec "implicite m: Manifeste[A] paramètre" et il sait le type générique de la Une sur le site d'appel, il va encapsuler la classe de A et de ses paramètres de type générique dans un Manifeste et de la rendre disponible à l'intérieur de la fonction. Toutefois, si elle ne pouvait pas comprendre le vrai type de l'Un, alors il n'a aucun moyen de la création d'un Manifeste. En d'autres termes, le Manifeste doit être transmis le long de la fonction d'appel de la chaîne si la fonction interne a besoin d'elle.

scala> def typeName[A](a: A)(implicit m: reflect.Manifest[A]) = m.toString
typeName: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String

scala> typeName(List(1))
res6: java.lang.String = scala.collection.immutable.List[int]

scala> def foo[A](a: A) = typeName(a)
<console>:5: error: could not find implicit value for parameter m:scala.reflect.Manifest[A].
       def foo[A](a: A) = typeName(a)
                                  ^

scala> def foo[A](a: A)(implicit m: reflect.Manifest[A]) = typeName(a)
foo: [A](a: A)(implicit m: scala.reflect.Manifest[A])java.lang.String

scala> foo(Set("hello"))
res8: java.lang.String = scala.collection.immutable.Set[java.lang.String]

3voto

santiajo Points 33

Pour compléter oxbow_lakes réponse: Il n'est pas possible et il semble que cela n'arrivera jamais (du moins bientôt).

L' (réfutable) raisons de la JVM ne soutiendra pas réifiée génériques semble être:

  • Une baisse des performances.
  • Il se casse la compatibilité descendante. Il peut être résolu de la duplication et de la fixation de beaucoup de bibliothèques.
  • Il peut être mis en œuvre à l'aide de manifeste: La "solution" et le plus grand obstacle.

Références:

Vous pouvez facilement comparer et de voir que l'impact de la performance est très perceptible. En particulier de la mémoire de la consommation augmente beaucoup.

Je crois que le chemin à parcourir est de disposer en option de la réification de la façon dont nous démarrer dans Scala avec Manifestes/TypeTags.

Si vous le pouvez et de le combiner avec de l'exécution de la spécialisation que vous pouvez viser haute performance et le code générique. Cependant, c'est sans doute pour objectif de Scala 2.12 ou 2.13.

1voto

Richard Gomes Points 1386

Une fois scalac est un compilateur, il a le potentiel d'être en mesure d'embellir le code généré avec les données des structures sont nécessaires pour mettre en œuvre réifiée génériques.

Ce que je veux dire, c'est que scalac aurait la capacité de voir...

// definition
class Klass[T] {
  value : T
}

//calls
floats  = Klass[float]
doubles = Klass[double]

... et de "développer" à quelque chose comme ceci:

// definition
class Klass_float {
  value : float
}
class Klass_double {
  value : double
}

// calls
floats  = Klass_float
doubles = Klass_double

Modifier

Le point est: le compilateur a la capacité de créer toutes les structures de données nécessaires qui démontrent à être nécessaire pour fournir des informations de type à l'exécution. Une fois que ce type d'information est disponible, la Scala exécution serait en profiter et peut effectuer tous les types de courant des opérations, nous pouvons imaginer. Il n'est pas question de savoir si la JVM fournit bytecode pour réifiée génériques ou pas. Le travail n'est pas fait par la JVM, mais par la Scala de la bibliothèque.

Si vous avez déjà écrit un débogueur symbolique (je l'ai fait!), vous savez que vous pouvez en principe 'dump' toutes les informations le compilateur a au moment de la compilation dans le binaire généré, l'adoption de toutes les données de l'organisation démontre être plus pratique pour la suite du traitement. C'est exactement la même idée: 'dump' toutes les informations de type de la Scala compilateur a.

En un mot, je ne vois pas pourquoi il ne pourrait pas être possible, n'a pas d'importance si la JVM fournit natif opérations pour réifiée génériques ou pas.

Une autre édition

IBM X10 démontre la capacité je parle de: il compile le code X10 sur le code Java, en tirant parti de réifiée des génériques sur les plates-formes Java. Comme je l'ai mentionné avant: Il peut être fait, mais seulement par des personnes qui savent comment un compilateur fonctionne et comment une bibliothèque d'exécution peuvent tirer parti de l'information "sous-évaluées" par le compilateur au moment de la compilation sur le code généré. Plus d'infos au: http://x10.sourceforge.net/documentation/papers/X10Workshop2012/slides/Takeuchi.pdf

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