Duplicata possible:
Quels sont quelques exemples d'utilisation des littéraux de symboles dans Scala?
Quel est le but de Symbol et pourquoi mérite-t-il une syntaxe spéciale littérale e. g. 'FooSymbol
?
Les symboles sont utilisés lorsque vous disposez d'un ensemble fermé d'identifiants que vous souhaitez pouvoir comparer rapidement. Lorsque vous avez deux instances de String
, il n'est pas garanti qu'elles soient internées [1], donc pour les comparer, vous devez souvent vérifier leur contenu en comparant les longueurs et même en vérifiant caractère par caractère si elles sont identiques. Avec les instances de Symbol
, les comparaisons sont une simple vérification de eq
(ie ==
En Java), donc elles sont à temps constant (ie O(1)) pour rechercher.
Ce type de structure a tendance à être davantage utilisé dans les langages dynamiques (notamment Ruby et le code LISP a tendance à utiliser beaucoup de symboles) car dans les langages à typage statique, on veut généralement restreindre l'ensemble d'articles par type.
Cela dit, si vous avez un magasin de clés/valeurs où il y a un ensemble restreint de clés, où il sera difficile d'utiliser un objet typé statique, une structure de style Map[Symbol, Data]
Pourrait être bonne pour vous.
ne note sur String
internement sur Java (et donc Scala): Java String
les s sont internés dans certains cas de toute façon, en particulier les littéraux de chaîne sont automatiquement internés, et vous pouvez appeler la méthode intern()
sur une instance de String
pour renvoyer une copie internée. Pas tous String
sont cependant internés, ce qui signifie que le runtime doit toujours effectuer la vérification complète à moins qu'il ne s'agisse de la même instance; l'internalisation accélère la comparaison de deux chaînes internées égales, mais n'améliore pas l'exécution de la comparaison de chaînes différentes. Symbol
a l'avantage d'être garanti d'être interné, donc dans ce cas une seule vérification d'égalité de référence est à la fois suffisante pour prouver l'égalité ou l'inégalité.
[1] L'internement est un processus par lequel, lorsque vous créez un objet, vous vérifiez s'il existe déjà un objet identique et l'utilisez s'il en existe un. Cela signifie que si vous avez deux objets qui sont égaux, ils sont précisément le même objet (c'est-à-dire qu'ils sont égaux de référence). L'inconvénient de cela est qu'il peut être coûteux de rechercher quel objet vous devez utiliser, et permettre aux objets d'être récupérés peut nécessiter une implémentation complexe.
Symbol
s sont internés.
Le but est que Symbol
soit plus efficace que String
s et Symbol
s avec le même nom sont référencés au même objet Symbol
(ayant donc le même hashcode) .
Jetez un oeil à cette lecture sur Ruby symboles: http://glu.ttono.us/articles/2005/08/19/understanding-Ruby-symbols
Vous ne pouvez obtenir que le nom d'un Symbol
:
scala> val aSymbol = 'thisIsASymbol
aSymbol: Symbol = 'thisIsASymbol
scala> assert("thisIsASymbol" == aSymbol.name)
Ce n'est pas très utile dans Scala et donc peu utilisé. En général, vous pouvez utiliser un symbole où vous souhaitez désigner un identifiant.
Par exemple, la fonction d'invocation de réflexion qui était prévue pour 2.8.0 utilisait la syntaxe obj o 'method(arg1, arg2)
où 'o' était une méthode ajoutée à Any et Symbol était ajouté la méthode apply (Any *) (les deux avec 'pimp ma bibliothèque').
Un autre exemple pourrait être si vous souhaitez créer un moyen plus simple de créer des documents HTML, puis au lieu d'utiliser "div" pour désigner un élément que vous écririez 'div. On peut alors imaginer ajouter des opérateurs à Symbol pour faire du sucre syntaxique pour créer des éléments