Mam poniżej:
(setq some-variable "less")
Jestem zdezorientowany, dlaczego muszę używać pojedynczego cytatu z, boundp
ale nie z bound-and-true-p
.
Przykład 1:
(when (boundp 'some-variable)
(message "some-variable is %s" some-variable))
Wynik:
„jakaś zmienna jest mniejsza”
Przykład 2a:
(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Wynik:
„jakaś zmienna jest mniejsza”
Przykład 2b:
(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
(message "some-variable is %s" some-variable))
Wynik:
i: Nieprawidłowy typ argumentu: symbolp, (cytuj zmienną)
setq
oznaczaset 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 (setq
jest to główny wyjątek).bound-and-true-p
to głupie makro. A raczej jego nazwa jest głupia. 99,99% czasu, kiedy chcesz to(and (boundp 'FOO) FOO)
zrobić, aby użyć wartościFOO
. Nie robisz tego tylko po to, aby uzyskać wartość prawdy. (1) Makro nie jest potrzebne - zastępowany kod jest trywialny i mały. (2) Nazwa wprowadza w błąd - chodzi o wartość zmiennej, a nie tylko o sprawdzenie, czy wartość zmiennej jestnil
.Odpowiedzi:
Krótka odpowiedź
Jeśli próbujesz użyć samej zmiennej, użyj
'some-variable
. Jeśli próbujesz użyć wartości przechowywanej w zmiennej, użyjsome-variable
.Wyjaśnienie
Definicja instrukcji znajduje się w instrukcji .
'
i(quote ...)
oba spełniają ten sam cel w emacs-lisp.Ma to na celu przekazanie nieocenionej formy do otaczającego środowiska, a nie jej ocenę.
W twoim przykładzie załóżmy, że mieliśmy następującą wyżej
Następnie ocena przebiega następująco:
Podczas gdy bez cytatu:
Lisp ocenia formularze, gdy są osiągane, poprzez cytowanie formularza, który uniemożliwia ocenę, tak aby przekazywana była rzeczywista zmienna (lub lista lub nazwa funkcji).
źródło
bound-and-truep
a pytanie brzmiało: dlaczego muszę cytować podczas korzystania,boundp
ale nie podczas korzystaniabound-and-truep
.boundp
wymaganiem symbolu (nieoceniony) abound-and-truep
potrzebą wartości zmiennej w punktorach (edytowanej po wstępnej odpowiedzi)Symbol, który znajduje się w pozycji niefunkcjonalnej, jest traktowany jako nazwa zmiennej. In
(function variable)
function
znajduje się w pozycji funkcji (po nawiasie otwierającym) ivariable
nie 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 zmiennejmy-variable
związanej jako zmienna”, a nie „to symbolmy-variable
związany jako zmienna.Dlaczego więc
bound-and-truep
zachowuje 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-p
jak wygląda definicja :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:
Jeśli napiszesz
to jest najpierw „przetłumaczone” na
a następnie jest to zwracane,
nil
jeślimy-variable
nie jest,boundp
lub wartośćmy-variable
(która oczywiście może byćnil
).Być może zauważyłeś, że rozszerzenie nie było
jak mogliśmy się spodziewać.
quote
to 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.jest krótką formą dla
`
w rzeczywistej definicjibound-and-true-p
również używane jest makro czytnika. Jeśli cytuje on symbol taki jak w`symbol
nim, 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 .jest równa
Powinno to odpowiedzieć na pytanie, dlaczego niecytowane symbole są czasami oceniane (zastępowane ich wartościami), a czasem nie; makra mogą służyć
quote
do zapobiegania ocenie symboli.Ale dlaczego
bound-and-true-p
makroboundp
nie 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, gdybyboundp
argument był cytowany automatycznie.bound-and-true-p
sł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:bound-and-true-p
moż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'
.źródło
Z kodu źródłowego
boundp
:boundp
oczekujesymbol
jako danych wejściowych.'some-variable
jest symbolem zmiennejsome-variable
.Z kodu źródłowego
bound-and-true-p
:bound-and-true-p
oczekujevariable
jako danych wejściowych.Wewnątrz
bound-and-true-p
makra otrzymuje symbol poprzez wykonanie(quote ,var)
. Więc jeśli wejście jestsome-variable
,(quote ,var)
spowoduje'some-variable
.Ale kiedy dać wejście
'some-variable
dobound-and-true-p
, pojawia się błąd:and: Wrong type argument: symbolp, (quote some-variable)
bo Makro nie spodziewa się symbol ('some-variable
) na wejściu.źródło
''symbol
ma sens. Oznacza to(quote (quote symbol))
. Przyczyną błędu jest to, że nie jest to prawidłowy argumentboundp
.