Mam przelotną wiedzę na temat innych Lispsów (szczególnie Scheme) od dawna. Ostatnio czytałem o Clojure . Widzę, że zawiera zarówno „symbole”, jak i „słowa kluczowe”. Znane mi symbole, ale nie ze słowami kluczowymi.
Czy inne Lispy mają słowa kluczowe? Czym różnią się słowa kluczowe od symboli innych niż mające inną notację (np. Dwukropki)?
Odpowiedzi:
Oto dokumentacja Clojure dotycząca słów kluczowych i symboli.
Słowa kluczowe są zwykle używane jako lekkie „ciągi ciągów”, np. Dla kluczy mapy mieszania lub wartości wysyłania metody multimetodowej. Symbole są zwykle używane do nazywania zmiennych i funkcji i rzadziej manipuluje się nimi bezpośrednio jako obiektami, z wyjątkiem makr i tym podobnych. Ale nic nie stoi na przeszkodzie, abyś używał symbolu wszędzie tam, gdzie używasz słowa kluczowego (jeśli nie masz nic przeciwko cytowaniu ich przez cały czas).
Najłatwiejszym sposobem zobaczenia różnicy jest przeczytanie
Keyword.java
iSymbol.java
w źródle Clojure. Istnieje kilka oczywistych różnic w implementacji. Na przykład symbol w Clojure może mieć metadane, a słowo kluczowe nie może.Oprócz składni z pojedynczym dwukropkiem można użyć podwójnego dwukropka, aby utworzyć słowo kluczowe kwalifikujące się do przestrzeni nazw.
user> :foo :foo user> ::foo :user/foo
Common Lisp ma słowa kluczowe, podobnie jak Ruby i inne języki. Oczywiście w tych językach są nieco inne. Niektóre różnice między słowami kluczowymi Common Lisp a słowami kluczowymi Clojure:
Słowa kluczowe w Clojure nie są symbolami.
user> (symbol? :foo) false
Słowa kluczowe nie należą do żadnej przestrzeni nazw, chyba że specjalnie je zakwalifikujesz:
user> (namespace :foo) nil user> (namespace ::foo) "user"
(Dziękuję Rainerowi Joswigowi za przedstawienie mi pomysłów na rzeczy do obejrzenia.)
źródło
(eval (eval ':a))
vs(eval (eval ''a))
. Czy są inne zalety? Jeśli chodzi o wydajność, są identyczne?Common Lisp ma symbole słów kluczowych.
Słowa kluczowe też są symbolami.
(symbolp ':foo) -> T
Co wyróżnia słowa kluczowe:
W przeciwnym razie słowa kluczowe są zwykłymi symbolami. Zatem słowa kluczowe mogą nazywać funkcje lub mieć listy właściwości.
Pamiętaj: w Common Lisp symbole należą do pakietu. Można to zapisać jako:
W przypadku symboli słów kluczowych oznacza to, że: foo, słowo kluczowe: foo i słowo kluczowe :: foo są tym samym symbolem. Dlatego te dwie ostatnie notacje zwykle nie są używane.
Tak więc: foo jest po prostu przetwarzane tak, aby znajdowało się w pakiecie KEYWORD, przy założeniu, że brak nazwy pakietu przed nazwą symbolu oznacza domyślnie pakiet KEYWORD.
źródło
Słowa kluczowe to symbole, które oceniają się same, więc nie musisz pamiętać o ich cytowaniu.
źródło
: słowa kluczowe są również traktowane specjalnie w wielu kolekcjach, pozwalając na bardzo wygodną składnię.
(:user-id (get-users-map))
jest taki sam jak
((get-users-map) :user-id)
to sprawia, że rzeczy są trochę bardziej elastyczne
źródło
W przypadku słów kluczowych wartości skrótu są obliczane i zapisywane w pamięci podręcznej podczas pierwszego konstruowania słowa kluczowego. Szukając słowa kluczowego jako klucza mieszającego, po prostu zwraca wstępnie obliczoną wartość skrótu. W przypadku ciągów znaków i symboli skrót jest obliczany ponownie przy każdym wyszukiwaniu.
Ponieważ te same nazwane słowa kluczowe są zawsze identyczne, zawierają one własne wartości skrótu. Ponieważ wyszukiwanie w mapach i zestawach jest wykonywane z kluczy hash, oznacza to lepszą wydajność wyszukiwania w przypadku wielu wyszukiwań, a nie w samym wyszukiwaniu.
źródło
Słowa kluczowe są globalne , symbole nie .
Ten przykład jest napisany w JavaScript, ale mam nadzieję, że pomoże to w zrozumieniu.
const foo = Symbol.for(":foo") // this will create a keyword const foo2 = Symbol.for(":foo") // this will return the same keyword const foo3 = Symbol(":foo") // this will create a new symbol foo === foo2 // true foo2 === foo3 // false
Kiedy konstruujesz symbol za pomocą
Symbol
funkcji, za każdym razem otrzymujesz odrębny / prywatny symbol. Gdy poprosisz o symbol za pomocąSymbol.for
funkcji, za każdym razem otrzymasz ten sam symbol.(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript
To wszystko jest takie samo.
Nazwy argumentów funkcji są lokalne. tj. nie słowa kluczowe.
(def foo (fn [x] (println x))) ; x is a symbol (def bar (fn [x] (println x))) ; not the same x (different symbol)
źródło