2010-08-24 14 views
45

Mögliche Duplizieren:
What are some example use cases for symbol literals in Scala?Zweck des Scala-Symbols?

Was ist der Zweck von Symbol ist und warum es einige spezielle wörtliche Syntax e verdienen. G. 'FooSymbol?

+2

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

+4

in Verbindung stehend: http://stackoverflow.com/questions/1324466/practical-examples-of-using-symbols-in-scala – Jesper

+0

Verwandte http://scala-programming-language.1934581.n4.nabble.com/The-need-for-symbol-literals-in-scala- td2313933.html Ich verstehe immer noch nicht, warum wir dafür eine spezielle Syntax brauchen. Scala hat bereits genug Syntax. –

Antwort

78

Symbole werden verwendet, wenn Sie einen geschlossenen Satz von Bezeichnern haben, die Sie schnell vergleichen können. Wenn Sie zwei String Instanzen haben, sind diese nicht garantiert interniert [1]. Um sie zu vergleichen, müssen Sie oft deren Inhalt überprüfen, indem Sie Längen vergleichen und sogar Zeichen für Zeichen prüfen, ob sie gleich sind. Mit Symbol Instanzen sind Vergleiche eine einfache Überprüfung (d. H. == in Java), so dass sie eine konstante Zeit (d. H. O (1)) sind, um nachzuschlagen.

Diese Art von Struktur wird tendenziell mehr in dynamischen Sprachen verwendet (insbesondere Ruby und Lisp Code neigt dazu, viele Symbole zu verwenden), da man in statisch getippten Sprachen die Menge der Elemente normalerweise nach Typ einschränken möchte.

Mit dem gesagt, wenn Sie einen Schlüssel/Wert speichern, wo es eine begrenzte Menge von Schlüsseln gibt, wo es unhandlich sein wird, ein statisches typisiertes Objekt zu verwenden, könnte eine Map[Symbol, Data]-style Struktur gut für Sie sein .

Ein Hinweis zu String auf Java Internierung (und damit Scala): Java String s in einigen Fällen ohnehin interniert; Insbesondere werden String-Literale automatisch interniert, und Sie können die intern()-Methode auf einer String-Instanz aufrufen, um eine interne Kopie zurückzugeben. Nicht alle String s sind jedoch interniert, was bedeutet, dass die Laufzeitumgebung immer noch die vollständige Prüfung durchführen muss, es sei denn, sie sind dieselbe Instanz. Internieren macht den Vergleich von zwei gleichen internierten Strings schneller, verbessert jedoch nicht die Laufzeit des Vergleichs verschiedener Strings.Symbol s Vorteil von garantiert zu interniert werden, so in diesem Fall ist eine einzige Referenz-Gleichheitsprüfung ausreicht, um Gleichheit oder Ungleichheit zu beweisen.

[1] Interning ist ein Prozess, bei dem Sie beim Erstellen eines Objekts prüfen, ob bereits ein gleiches vorhanden ist, und dieses dann verwenden, wenn dies der Fall ist. Dies bedeutet, dass, wenn Sie zwei Objekte haben, die gleich sind, sie genau das gleiche Objekt sind (d. H. Sie sind Referenz gleich). Die Nachteile davon sind, dass es teuer sein kann, nachzusehen, welches Objekt Sie verwenden müssen, und dass das Sammeln von Objekten überflüssig wird, kann eine komplexe Implementierung erfordern.

6

Symbol s sind interniert.

Der Zweck besteht darin, dass Symbol sind effizienter als String s und Symbol s mit dem gleichen Namen auf das gleiche Symbol Objekt verwiesen werden (so den gleichen Hash-Code hat).

Werfen Sie einen Blick auf diese Lese zu Ruby Symbole: http://glu.ttono.us/articles/2005/08/19/understanding-ruby-symbols

Sie können nur den Namen eines Symbol erhalten:

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

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

Ja, das auch in der .NET CLR. –

+8

Dieser Eintrag ist ein wenig irreführend; Wenn Sie sagen, dass Sie den gleichen Hashcode haben, haben alle gleichen Strings den gleichen Hashcode. Wo sie sich unterscheiden, ist, dass sie genau die gleiche Objektinstanz sind, was bedeutet, dass der Vergleich derselben nicht das Aufrufen einer komplexen "Gleich" -Methode beinhaltet, die jedes Zeichen vergleicht; Sie müssen nur die Speicherplätze vergleichen (d. h. == in Java oder "eq" in Scala). IttayD: Das ist nicht wahr; Literale Strings werden interniert und Sie können Strings mit String.intern() internieren. – Calum

+1

Strings werden nicht zu 100% immer interniert http://javatechniques.com/public/java/docs/basics/string-equality.html –

5

Es ist nicht sehr nützlich in Scala und somit nicht weit verbreitet. Im Allgemeinen können Sie ein Symbol verwenden, an dem Sie einen Bezeichner festlegen möchten.

Zum Beispiel die Reflektionsaufruffunktion, die für 2.8.0 geplant war, verwendete die Syntax obj o 'method(arg1, arg2) wobei 'o' eine zu Any hinzugefügte Methode war und Symbol die Methode apply (Any *) hinzugefügt wurde (beide mit 'pimp my library ').

Ein anderes Beispiel könnte sein, wenn Sie eine einfachere Möglichkeit zum Erstellen von HTML-Dokumenten erstellen möchten, anstatt "div" zu verwenden, um ein Element zu bestimmen, das Sie "div. Dann kann man sich vorstellen, Operatoren zu Symbol hinzuzufügen, um syntaktischen Zucker zum Erzeugen von Elementen zu erzeugen.

+0

Für das letzte Beispiel gibt es keinen Grund, keine Zeichenfolge anstelle eines Symbols zu verwenden. –

+1

Der Grund ist, dass in HTML "div" eine Kennung ist, nicht nur eine zufällige Zeichenfolge. Deshalb habe ich HTML und nicht XML (wo ein Element einen beliebigen Namen haben kann) erwähnt. Der Grund des Symbols ist also semantisch. Funktional gesehen gibt es keinen Unterschied – IttayD

+0

@IttayD, ad.HTML, Symbol oder Zeichenfolge, es ist egal, weil Sie einen Tippfehler sowieso machen können. – greenoldman