Un symbole qui est en position non fonctionnelle est traité comme le nom d'une variable. In (function variable)
function
est en position de fonction (après la parenthèse ouvrante) et variable
ne l'est pas. Sauf si les variables explicitement citées sont remplacées par leurs valeurs.
Si vous deviez écrire (boundp my-variable)
cela signifierait "est le symbole qui est stocké dans la valeur de la variable my-variable
liée en tant que variable" et non "est le symbole my-variable
lié en tant que variable.
Alors pourquoi bound-and-truep
se comporte-t-il différemment?
Il s'agit d'une macro et les règles d'évaluation normales (fonction) ne s'appliquent pas ici, les macros sont libres de décider si et quand leurs arguments sont évalués. Ce que les macros font réellement, c'est d'une manière ou d'une autre de transformer les arguments et de renvoyer le résultat sous forme de liste, qui est ensuite évaluée. La transformation et l'évaluation finale se produisent à différents moments, appelés temps de macro-expansion et temps d'évaluation.
Voici à quoi bound-and-true-p
ressemble la définition de :
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
Cela utilise des macros de lecteur qui sont différentes des macros lisp (plus d'informations ci-dessous). Pour ne pas compliquer cela, nous ne devons pas utiliser de macros de lecture:
(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))
Si vous écrivez
(bound-and-true-p my-variable)
qui est d'abord "traduit" en
(and (boundp 'my-variable) my-variable)
et ensuite cela est évalué en retournant nil
if my-variable
n'est pas boundp
ou bien la valeur de my-variable
(qui bien sûr peut aussi être nil
).
Vous avez peut-être remarqué que l'extension n'était pas
(and (boundp (quote my-variable)) my-variable)
comme on aurait pu s'y attendre. quote
est une forme spéciale, pas une macro ou une fonction. Comme les macros, les formulaires spéciaux peuvent faire n'importe quoi avec leurs arguments. Cette forme spéciale particulière renvoie simplement son argument, ici un symbole, au lieu de la valeur variable du symbole. C'est en fait le seul but de ce formulaire spécial: empêcher l'évaluation! Les macros ne peuvent pas le faire par elles-mêmes, elles doivent les utiliser quote
pour le faire.
Alors quoi de neuf '
? Il s'agit d'une macro de lecture qui, comme mentionné ci-dessus, n'est pas la même chose qu'une macro lisp . Alors que les macros sont utilisées pour transformer le code / les données, les macros du lecteur sont utilisées plus tôt lors de la lecture du texte afin de transformer ce texte en code / données.
'something
est une forme abrégée pour
(quote something)
`
utilisé dans la définition réelle de bound-and-true-p
est également une macro de lecture. S'il cite un symbole comme dans, `symbol
il est équivalent à 'symbol
, mais quand est utilisé pour citer une liste comme dans, `(foo bar ,baz)
il se comporte différemment dans la mesure où les formulaires préfixés ,
sont évalués.
`(constant ,variable)
est équivalent à
(list (quote constant) variable))
Cela devrait répondre à la question de savoir pourquoi les symboles non cités sont parfois évalués (remplacés par leurs valeurs) et parfois non; les macros peuvent être utilisées quote
pour empêcher l'évaluation d'un symbole.
Mais pourquoi bound-and-true-p
une macro boundp
ne l'est-elle pas? Nous devons être en mesure de déterminer si des symboles arbitraires, qui ne sont pas connus avant l'exécution, sont liés en tant que symboles. Cela ne serait pas possible si l' boundp
argument était automatiquement cité.
bound-and-true-p
est utilisé pour déterminer si une variable connue est définie et si c'est le cas, utilisez sa valeur. Ceci est utile si une bibliothèque a une dépendance facultative sur une bibliothèque tierce comme dans:
(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-p
pourrait être défini comme une fonction et nécessiter la citation de l'argument, mais parce qu'il est destiné aux cas où vous savez à l'avance quelle variable vous vous souciez d'une macro a été utilisée pour vous éviter d'avoir à taper le '
.
setq
signifieset quoted
et était à l'origine une macro qui s'est développée(set 'some-variable "less")
. En général, Elisp n'est pas terriblement cohérent à propos des arguments entre guillemets et sans guillemets, mais toute fonction (pas une macro) qui doit interagir avec une variable au lieu d'une valeur prendra son argument entre guillemets (setq
étant une exception majeure).