2010-08-24 5 views
45

Possible en double:
What are some example use cases for symbol literals in Scala?But du symbole de Scala?

Quel est le but de Symbol et pourquoi il mérite une spéciale littérale syntaxe e. g. 'FooSymbol?

+2

Relatif: http://stackoverflow.com/questions/780287/what-are-some-example-use-cases-for-symbol-literals-in-scala – delnan

+4

Connexe: http://stackoverflow.com/questions/1324466/examples-pratiques-d'emploi-symboles-en-scala – Jesper

+0

http://scala-programming-language.1934581.n4.nabble.com/The-need-for-symbol-literals-in-scala- td2313933.html Je ne comprends toujours pas pourquoi nous avons besoin d'une syntaxe spéciale pour cela. Scala a déjà assez de syntaxe. –

Répondre

78

Les symboles sont utilisés lorsque vous avez un ensemble fermé d'identifiants que vous voulez pouvoir comparer rapidement. Lorsque vous avez deux instances String, elles ne sont pas garanties d'être internées [1], donc pour les comparer vous devez souvent vérifier leur contenu en comparant les longueurs et même en vérifiant les caractères les uns après les autres s'ils sont identiques. Avec les instances Symbol, les comparaisons sont une simple vérification eq (c'est-à-dire == en Java), elles sont donc à temps constant (c'est-à-dire O (1)) à rechercher. Ce type de structure tend à être davantage utilisé dans les langages dynamiques (notamment le code Ruby et Lisp a tendance à utiliser beaucoup de symboles) puisque dans les langages statiques, on veut généralement restreindre l'ensemble des items par type. Cela dit, si vous avez un magasin de clé/valeur où il y a un ensemble restreint de clés, où il va être difficile d'utiliser un objet statique, une structure de type Map[Symbol, Data] pourrait bien vous convenir .

Une note sur String interner sur Java (et donc Scala): Java String s sont internées 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 String pour renvoyer une copie interne. Cependant, tous les String s ne sont pas internés, ce qui signifie que le runtime doit toujours effectuer la vérification complète sauf s'il s'agit de la même instance. l'internalisation permet de comparer deux chaînes internées égales plus rapidement, mais n'améliore pas l'exécution de la comparaison de chaînes différentes. s être garanti pour être interné, 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'internalisation est un processus par lequel, lorsque vous créez un objet, vous vérifiez si un objet égal existe déjà, et utilisez celui-ci s'il le fait. Cela signifie que si vous avez deux objets égaux, ils sont exactement le même objet (c'est-à-dire qu'ils sont égaux). Les inconvénients sont qu'il peut être coûteux de rechercher quel objet vous devez utiliser, et permettre aux objets d'être collectés peut nécessiter une implémentation complexe.

6

Symbol s sont internés.

Le but est que Symbol sont plus efficaces que String s et Symbol s avec le même nom sont refered au même objet Symbol (afin d'avoir la même hashcode).

Jetez un oeil à cette lecture sur les symboles Ruby: http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols

Vous ne pouvez obtenir le nom d'un Symbol:

scala> val aSymbol = 'thisIsASymbol 
aSymbol: Symbol = 'thisIsASymbol 

scala> assert("thisIsASymbol" == aSymbol.name) 
+0

Oui, le dans le .NET CLR, aussi. –

+8

Cette entrée est un peu trompeuse; où vous dites "avoir le même hashcode", toutes les chaînes égales ont le même hashcode. Là où ils diffèrent, c'est qu'ils sont précisément la même instance d'objet, ce qui signifie que leur comparaison n'implique pas l'appel d'une méthode complexe «égale» qui comparera chaque caractère; Vous n'avez qu'à comparer les emplacements de mémoire (c'est-à-dire == dans Java ou "eq" dans Scala). IttayD: Ce n'est pas vrai; Les chaînes littérales sont internées et vous pouvez internaliser des chaînes avec String.intern(). – Calum

+1

Les chaînes ne sont pas 100% toujours internalisées http://javatechniques.com/public/java/docs/basics/string-equality.html –

5

Il est pas très utile à Scala et donc pas largement utilisé. En général, vous pouvez utiliser un symbole où vous souhaitez désigner un identifiant. Par exemple, la fonction d'appel de réflexion 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 a été ajoutée la méthode apply (Any *) (les deux avec 'pimp my library' ').

Un autre exemple pourrait être si vous voulez créer un moyen plus facile de créer des documents HTML, puis au lieu d'utiliser "div" pour désigner un élément que vous écrivez 'div. Ensuite, on peut imaginer ajouter des opérateurs à Symbol pour faire du sucre syntaxique pour créer des éléments

+0

Pour le dernier exemple, il n'y a aucune raison de ne pas utiliser une chaîne au lieu d'un symbole. –

+1

La raison en est que HTML 'div' est un identifiant, pas seulement une chaîne aléatoire. C'est pourquoi j'ai mentionné HTML et non XML (où un élément peut être de n'importe quel nom). Donc, la raison du symbole est sémantique. Fonctionnellement parlant, il n'y a pas de différence – IttayD

+0

@IttayD, ad.HTML, symbole ou chaîne de caractères, cela n'a pas d'importance car vous pouvez faire une faute de frappe quand même. – greenoldman