Jakie są przykładowe przypadki użycia literałów symboli w Scali?


93

Użycie literałów symboli nie jest od razu jasne z tego, co przeczytałem w Scali. Czy ktoś chciałby podzielić się niektórymi zastosowaniami w prawdziwym świecie?

Czy istnieje określony idiom Java objęty literałami symboli? Jakie języki mają podobne konstrukcje? Pochodzę z języka Python i nie jestem pewien, czy jest coś podobnego w tym języku.

Co zmotywowałoby mnie do użycia „HelloWorld vs„ HelloWorld ”?

Dzięki

Odpowiedzi:


77

W języku Java symbole są łańcuchami wewnętrznymi. Oznacza to na przykład, że porównanie równości odniesień ( eqw Scali i ==Javie) daje taki sam wynik jak normalne porównanie równości ( ==w Scali i equalsJavie): 'abcd eq 'abcdzwróci wartość true, ale "abcd" eq "abcd"może nie, w zależności od kaprysów JVM (cóż, powinno dla literałów, ale nie dla łańcuchów tworzonych dynamicznie).

Inne języki, które używają symboli to Lisp (który używa 'abcdjak Scala), Ruby ( :abcd), Erlang i Prolog ( abcd; nazywane są atomami zamiast symboli).

Użyłbym symbolu, gdy nie obchodzi mnie struktura łańcucha i używam go wyłącznie jako nazwy czegoś. Na przykład, jeśli mam tabelę bazy danych reprezentującą płyty CD, która zawiera kolumnę o nazwie „cena”, nie obchodzi mnie, że drugi znak w polu „cena” to „r”, czy też konkatenacja nazw kolumn; więc biblioteka bazy danych w Scali mogłaby rozsądnie używać symboli dla nazw tabel i kolumn.


25
Prawdopodobnie warto pamiętać, że == w Scali robi to .equals, więc tak naprawdę różnica byłaby w przypadku użycia metody „eq”, która odwołuje się do równości. Zaletą jest jednak to, że porównanie symboli jest niezwykle tanie.
— Calum

@Calum, as to porównanie dwóch ciągów. Stażyści Java (mniej więcej) wszystkie ciągi.
— Elazar Leibovich

4
@Elazar: Czy to naprawdę prawda? Miałem wrażenie, że Java internuje tylko literały (tj. Prawie wszystkie łańcuchy w trywialnych przykładach i prawie żadnych łańcuchów w oprogramowaniu produkcyjnym). Powiedziawszy, że przypadki użycia symboli są zwykle wartościami dosłownymi (wątpię, byś często tworzył je od zera), więc prawdopodobnie główną zaletą, jaką otrzymujesz, jest po prostu typ bardziej opisowy.
— Calum

1
@Elazar Nie są, ponieważ symbole mogą polegać na internalizacji ich wartości, podczas gdy w przypadku łańcuchów jest to opcjonalne i może zoptymalizować niektóre przypadki użycia. Symbole bardziej przypominają wyliczenia tworzone dynamicznie niż cokolwiek innego. Rozwinąłem to na podstawie odpowiedzi, którą połączyłem w mojej ostatniej odpowiedzi; przeczytaj to po więcej.
— Calum,

3
A więc „witaj, świecie!” jest sekwencyjną kolekcją znaków, podczas gdy „helloWorld jest wartością przyjazną ludziom, a nie 14392.
— CW Holeman II

26

Jeśli masz w kodzie zwykłe ciągi reprezentujące nazwy metod powiedz, które być może są przekazywane, nie do końca przekazujesz rzeczy w odpowiedni sposób. Jest to rodzaj problemu z granicami danych / kodu, nie zawsze łatwo jest narysować linię, ale gdybyśmy mieli powiedzieć, że w tym przykładzie te nazwy metod są bardziej kodem niż danymi, to chcemy, aby coś wyraźnie to zidentyfikowało .

W grę wchodzi literał symbolu, który wyraźnie rozróżnia wszystkie stare dane łańcuchowe z konstrukcją używaną w kodzie. Po prostu jest tam, gdzie chcesz wskazać, nie są to tylko niektóre dane tekstowe, ale w rzeczywistości w jakiś sposób część kodu. Pomysł polegający na tym, że rzeczy takie jak twoje IDE podkreśliłyby to inaczej, a biorąc pod uwagę narzędzia, możesz je refaktoryzować, zamiast wyszukiwać / zastępować tekst.

Ten link dość dobrze to omawia.


2
To jest pomocne wyjaśnienie. To sprawia, że ​​myślę w kategoriach alternatyw dla wyliczeń - które mogą być niezdarne
— javadba

2

Python utrzymuje wewnętrzną, globalną tabelę „wewnętrznych łańcuchów” z nazwami wszystkich zmiennych, funkcji, modułów itp. Dzięki tej tabeli interpreter może szybciej wyszukiwać i optymalizować. Możesz wymusić ten proces internfunkcją ( sys.internw python3).

Ponadto Java i Scala automatycznie używają „wewnętrznych ciągów znaków” w celu przyspieszenia wyszukiwania. Dzięki scali możesz użyć internmetody do wymuszenia stażysty ciągu, ale ten proces nie działa ze wszystkimi ciągami. Symbole korzystają z gwarancji internowania, więc jedno sprawdzenie równości odniesienia wystarczy, aby udowodnić równość lub nierówność.


1

Uwaga: Symbolszostaną wycofane, a następnie usunięte w Scala 3 (dotty).

Źródła: http://dotty.epfl.ch/docs/reference/dropped-features/symlits.html

Z tego powodu osobiście odradzam używanie go Symbols(przynajmniej w nowym kodzie scala). Jak stwierdza dokumentacja dotty:

Literały symboli nie są już obsługiwane

zamiast tego zaleca się użycie zwykłego literału ciągu [...]


1
Dziki, że opublikowałem to pytanie 11 lat temu. Dzięki za kontynuację
— Joe Holloway
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.