Co robi „symbol-wartość”?

13

Dokumenty nie uczyniły mnie mądrzejszym:

Ta funkcja zwraca wartość zapisaną w komórce wartości symbolu. To tutaj przechowywana jest bieżąca (dynamiczna) wartość zmiennej. Jeśli zmienna nie ma lokalnego powiązania, jest to po prostu jej wartość globalna. Jeśli zmienna jest nieważna, sygnalizowany jest błąd zmiennej nieważności.

Jaki jest sens wartości symbolicznej? Gdzie i kiedy muszę go użyć?

The Unfun Cat
źródło
3
Dziękujemy za próbę znalezienia odpowiedzi przez zadawanie pytań Emacsowi. To jest właściwe podejście: najpierw zapytaj Emacsa, a następnie zapytaj tutaj o to, co nadal nie jest jasne, dając nam znać w swoim pytaniu, co już próbowałeś. Sława!
Drew

Odpowiedzi:

13

Potrzebujesz go, gdy w kodzie Elisp chcesz uzyskać wartość symbolu, to znaczy jego wartość, gdy jest uważana za zmienną.

Pamiętaj, że symbol Elisp ma kilka cech / cech:

  • Ma nazwę (która funkcja symbol-namedaje)
  • Może mieć wartość, gdy jest uważana za zmienną (co symbol-valuedaje)
  • Może nazwać funkcję, jeśli zostanie uznana za funkcję (która symbol-functiondaje)
  • Ma listę właściwości (która symbol-plistdaje)

Pomyśl o symbolu jako obiekcie o różnych atrybutach.

Rysował
źródło
1
Zauważ też, że (jak wskazuje dokumentacja) symbol-valuezawsze zwraca dynamiczne powiązanie dla symbolu. W ten sposób nie można uzyskać wartości leksykalnych.
phils
2
Zobacz także C-h i g (elisp) Symbol Components RETdokumentację na temat różnych komórek / komponentów symboli.
phils
@phils: Hm, zastanawiam się: (setq lexical-binding t) (let ((v 42)) (message "lex: %S, val: %S" lexical-binding (symbol-value 'v))). Ale tak, to co jest napisane na (Elisp) Lexical Binding: „ funkcje jak symbol-value, boundp'i set'tylko pobierać lub modyfikować dynamikę danej zmiennej wiązania (czyli zawartość wartość komórki jest jej symbol) ”. Jednak nic o tym nie mówi się Symbol Components.
Drew
10

(Doh, @Drew już omówił niektóre z poniższych. W każdym razie, oto kilka dodatkowych szczegółów.)

Jak wyjaśnia strona podręcznika na temat symboli , każdy symbol ma cztery składniki (komórki): komórkę nazwy wydruku, komórkę wartości, definicję funkcji i listę właściwości. Komórka wartości lub komórka funkcji może być nieważna, a lista właściwości może być zerowa.

Jak wskazano w instrukcji:

Ponieważ każdy symbol ma osobne komórki wartości i funkcji, nazwy zmiennych i nazwy funkcji nie powodują konfliktu.

Dlatego możesz na przykład:

(setq test "kittens")
(defun test ()
  (message "puppies"))
(symbol-value 'test)    ; => "kittens"
(symbol-function 'test) ; => (lambda nil (message "puppies"))
Dan
źródło
1
Ach, że jest to wartość, a nie funkcja, znacznie ułatwia zrozumienie. Dzięki.
Unfun Cat
8

Oto trochę odniesień historycznych (jeszcze się nie urodziłem, kiedy miały miejsce opisane wydarzenia, więc może ktoś bardziej kompetentny mnie poprawi. Wszystko po przeczytaniu starych artykułów i niektórych książek).

Po rezygnacji z wyłączenia odpowiedzialności wydaje się, że w czasach Fortran kontra Lisp „symboliczne” było rodzajem modnego hasła, jakim jest dzisiaj „obiektowe”. Tj. Programy były zwykle postrzegane jako po prostu ogromne formuły matematyczne, w których liczby zostaną w końcu podłączone, a symbole zastępcze dla liczb były nieistotne. Wszystkie informacje symboliczne zawarte w programie znikną, gdy tylko program zostanie uruchomiony, skompilowany lub zinterpretowany. Nowością Lisp było to, że pozwalało na zachowanie symboli w programie nawet po jego uruchomieniu, kompilacji lub interpretacji. To zainspirowało taką terminologię, jak „algebra symboliczna” (jak w przypadku manipulacji formułami algebraicznymi wykonywanymi na papierze / tablicy, a nie przez bezpośrednie obliczenia). Aby wesprzeć to (i inne symboliczne rzeczy) symbole miały być wyposażone w nazwę i niektóre właściwości. Z nie-symbolicznego punktu widzenia można powiedzieć, że „symbole są po prostu nazwanymi wskaźnikami”, i chociaż nie jest to prawdą, jeśli w ogóle są bardziej wskaźnikami do struktur, ale dla celów praktycznych symbole są desygnatorami lewej strona strony pary o zmiennej wartości. Pozwala to również zobaczyćsymbol-value działają jako dereferencje wskaźnika w językach innych niż symboliczne.

Współczesne Lisps różnią się tym, ile wartości można skojarzyć z jednym symbolem (załóżmy, że masz nie-symboliczny język z wieloma stosami / stosami pamięci, możesz sobie wyobrazić sytuację, w której ten sam wskaźnik ma znaczenie, gdy jest interpretowany w kontekście różnych stosów / hałdy). Tak więc języki Lisp2 (Emacs Lisp jest jednym z takich języków) mają osobne miejsce na funkcje i zmienne, dlatego też istnieje również „ symbol-function, który„ odznacza wskaźnik wskazujący miejsce na funkcję ”. Schemat nie ma tego specjalnego miejsca do przechowywania, a Clojure AFAIK, nie ma ani tego, ani symbol-plist.

wvxvw
źródło
7

Małe demo:

(setq v1 10)
;;10
v1
;;10
(setq v2 'v1)
;;v1
v2
;;v1
(symbol-value v2)
;;10 
abo-abo
źródło