関数以外の位置にあるシンボルは、変数の名前として扱われます。In (function variable)
function
は関数の位置(開き括弧の後)にあり、そうでvariable
はありません。明示的に引用された変数がそれらの値で置き換えられない限り。
書く場合(boundp my-variable)
は、「変数my-variable
としてバインドされた変数の値に格納されているシンボルである」ことを意味し、「変数としてバインドされているシンボルではありませんmy-variable
。
では、なぜbound-and-truep
異なる振る舞いをするのでしょうか?
これはマクロであり、通常の(関数)評価ルールはここでは適用されません。マクロは引数が評価されるかどうか、いつ評価されるかを自由に決定できます。マクロが実際に行うのは、何らかの方法で引数を変換し、結果をリストとして返し、それを評価することです。変換と最終評価は、マクロ展開時間と評価時間と呼ばれる異なる時間に行われます。
これはの定義がどのbound-and-true-p
ように見えるかです:
(defmacro bound-and-true-p (var)
"Return the value of symbol VAR if it is bound, else nil."
`(and (boundp (quote ,var)) ,var))
これは、lispマクロとは異なるリーダーマクロを使用します(詳細は以下を参照)。これをさらに複雑にしないために、リーダーマクロを使用しないようにします。
(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))
書くなら
(bound-and-true-p my-variable)
それは最初に「翻訳」されます
(and (boundp 'my-variable) my-variable)
そして、それが評価され、nil
if my-variable
が返されないboundp
か、そうでない場合はmy-variable
(もちろんにもなりますnil
)。
あなたは拡張がそうではなかったことに気づいたかもしれません
(and (boundp (quote my-variable)) my-variable)
予想通りでした。quote
マクロや関数ではなく、特別な形式です。マクロと同様に、特別なフォームは引数を使用して何でもできます。この特定の特別な形式は、シンボルの変数値の代わりに、引数、ここではシンボルを返すだけです。それが実際にこの特別なフォームの唯一の目的です:評価を防ぐ!マクロはそれを単独で行うことはできませんquote
。そうするために使用する必要があります。
どうしたの'
?これはリーダーマクロです。上記のようにLispマクロとは異なります。マクロはコード/データを変換するために使用されますが、リーダーマクロは、テキストをコード/データに変換するためにテキストを読み取るときに以前に使用されます。
'something
は短い形式です
(quote something)
`
実際の定義でbound-and-true-p
も使用されるのは、リーダーマクロです。のようにシンボルを引用する場合、`symbol
と同等ですが'symbol
、の`(foo bar ,baz)
ようにリストを引用するためにwhenを使用すると、接頭辞が付いて,
いるフォームが評価されるという点で動作が異なります。
`(constant ,variable)
と同等です
(list (quote constant) variable))
これは、引用符で囲まれていないシンボルが評価される(値で置き換えられる)場合と評価されない場合があるという質問に答える必要があります。マクロはquote
、シンボルが評価されないようにするために使用できます。
しかし、なぜbound-and-true-p
マクロboundp
はそうではないのですか?実行時までわからない任意のシンボルがシンボルとしてバインドされているかどうかを判断できる必要があります。boundp
引数が自動的に引用されている場合、これは不可能です。
bound-and-true-p
既知の変数が定義されているかどうかを判断し、定義されている場合はその値を使用します。これは、次のように、ライブラリにサードパーティライブラリへのオプションの依存関係がある場合に便利です。
(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
関数として定義することができ、引数を引用符で囲む必要がありますが、マクロを気にする変数を使用して、'
。
setq
意味しset quoted
、元々はに展開されたマクロでした(set 'some-variable "less")
。一般的に、Elispは引用引数と非引用引数についてひどく一貫していませんが、値の代わりに変数と対話する必要がある関数(マクロではない)は引数を引用符で囲みます(setq
主要な例外です)。