Symbol, który znajduje się w pozycji niefunkcjonalnej, jest traktowany jako nazwa zmiennej. In (function variable) functionznajduje się w pozycji funkcji (po nawiasie otwierającym) i variablenie jest. Chyba, że zmienne podane wprost są zastępowane ich wartościami.
Jeśli miałbyś pisać (boundp my-variable), oznaczałoby to „to symbol, który jest przechowywany w wartości zmiennej my-variablezwiązanej jako zmienna”, a nie „to symbol my-variablezwiązany jako zmienna.
Dlaczego więc bound-and-truepzachowuje się inaczej?
Jest to makro i nie mają tu zastosowania normalne reguły oceny (funkcji), makra mogą swobodnie decydować, czy i kiedy ich argumenty zostaną ocenione. Makra faktycznie przekształcają argumenty i zwracają wynik jako listę, która jest następnie analizowana. Transformacja i ocena końcowa odbywają się w różnych momentach, zwanych czasem ekspansji makr i czasem oceny.
Oto bound-and-true-pjak wygląda definicja :
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
Używa to makr czytnika, które różnią się od makr lisp (więcej na ten temat poniżej). Aby to nie komplikować, nie używajmy żadnych makr czytników:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
(list 'and (list 'boundp (list 'quote var)) var))
Jeśli napiszesz
(bound-and-true-p my-variable)
to jest najpierw „przetłumaczone” na
(and (boundp 'my-variable) my-variable)
a następnie jest to zwracane, niljeśli my-variablenie jest, boundplub wartość my-variable(która oczywiście może być nil).
Być może zauważyłeś, że rozszerzenie nie było
(and (boundp (quote my-variable)) my-variable)
jak mogliśmy się spodziewać. quoteto specjalna forma, a nie makro lub funkcja. Podobnie jak makra, specjalne formularze mogą zrobić wszystko z ich argumentami. Ta szczególna specjalna forma po prostu zwraca swój argument, tutaj symbol, zamiast zmiennej wartości symbolu. To właściwie jedyny cel tej specjalnej formy: zapobieganie ewaluacji! Makra nie można zrobić na własną rękę, trzeba użyć quote, aby to zrobić.
Więc o co chodzi '? Jest to makro czytnika , które, jak wspomniano powyżej, nie jest tym samym, co makro lisp . Podczas gdy makra są używane do przekształcania kodu / danych, makra czytające są używane wcześniej podczas czytania tekstu w celu przekształcenia tego tekstu w kod / dane.
'something
jest krótką formą dla
(quote something)
`w rzeczywistej definicji bound-and-true-prównież używane jest makro czytnika. Jeśli cytuje on symbol taki jak w `symbolnim, jest on równoważny 'symbol, ale kiedy jest używany do cytowania listy, ponieważ `(foo bar ,baz)zachowuje się inaczej w tym, że ,oceniane są formularze z prefiksem .
`(constant ,variable)
jest równa
(list (quote constant) variable))
Powinno to odpowiedzieć na pytanie, dlaczego niecytowane symbole są czasami oceniane (zastępowane ich wartościami), a czasem nie; makra mogą służyć quotedo zapobiegania ocenie symboli.
Ale dlaczego bound-and-true-pmakro boundpnie jest? Musimy być w stanie ustalić, czy dowolne symbole, które nie są znane do czasu wykonania, są powiązane jako symbole. Nie byłoby to możliwe, gdyby boundpargument był cytowany automatycznie.
bound-and-true-psłuży do ustalenia, czy znana zmienna jest zdefiniowana, a jeśli tak, użyj jej wartości. Jest to przydatne, jeśli biblioteka ma opcjonalną zależność od biblioteki innej firmy, jak w:
(defun foo-get-value ()
(or (bound-and-true-p bar-value)
;; we have to calculate the value ourselves
(our own inefficient or otherwise undesirable variant)))
bound-and-true-pmożna zdefiniować jako funkcję i wymagać cytowania argumentu, ale ponieważ jest on przeznaczony do przypadków, w których wiadomo z góry, jaką zmienną, na której Ci zależy, makro użyto, aby uniknąć konieczności wpisywania '.
setqoznaczaset quoted, i pierwotnie było makrem, które się rozszerzyło(set 'some-variable "less"). Ogólnie rzecz biorąc, Elisp nie jest strasznie konsekwentny w argumentach cytowanych i niecytowanych, ale każda funkcja (nie makro), która musi wchodzić w interakcje ze zmienną zamiast wartości, przyjmuje cytowany argument (setqjest to główny wyjątek).