変数名の前に単一引用符を使用するタイミングまたは使用しないタイミングを知る方法は?


31

私は以下を持っています:

(setq some-variable "less")

boundpなく単一引用符を使用する必要がある理由がわかりませんbound-and-true-p

例1:

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))

結果:

「変数が少ない」

例2a:

(when (bound-and-true-p some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

結果:

「変数が少ない」

例2b:

(when (bound-and-true-p 'some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))

結果:

and:間違った型の引数:symbolp、(quote some-variable)


5
これはをsetq意味しset quoted、元々はに展開されたマクロでした(set 'some-variable "less")。一般的に、Elispは引用引数と非引用引数についてひどく一貫していませんが、値の代わりに変数と対話する必要がある関数(マクロではない)は引数を引用符で囲みます(setq主要な例外です)。
shosti 14年

2
FWIW bound-and-true-pは、愚かなマクロです。むしろ、その名前は愚かです。したいときの99.99%は、の値(and (boundp 'FOO) FOO)使用するために行いますFOO。真理値を得るためだけにやるのではありません。(1)マクロは必要ありません-それが置き換えるコードは簡単で小さいです。(2)名前は誤解を招く-変数値がであるかどうかをテストするだけでなく、変数値に関するものですnil
ドリュー

回答:


24

短い答え

変数自体を使用しようとしている場合は、を使用します'some-variable。変数に保存されている値を使用しようとしている場合は、を使用しますsome-variable

  • boundpはシンボルを使用するため、関数を含むバインド可能なものすべてを調べます。値が何であるかではなく、一致するシンボルがあるかどうかだけを考慮します。
  • bound-and-truepはvarを使用して値を返します。この場合、関数にシンボルの値を提供する必要があります。シンボルvarがバインドされていない場合、または値がnilの場合、nilを返します。

説明

マニュアルの定義については、マニュアルを参照しください。

'そして、(quote ...)両方ともemacs-lispで同じ目的を果たします。

この目的は、未評価のフォームを評価するのではなく、周囲の環境に渡すことです。

あなたの例では、次の上位があったと仮定します

(setq some-variable "less") ;; Rather than just 't for clarity

次に、評価は次のようになります。

(when (boundp 'some-variable) 
   (message "some-variable is %s" some-variable))
;; ==> (boundp 'some-variable) ; 't
;; ==> some-variable is "less"

一方、引用符なし:

(when (boundp some-variable) ;; Note that using single-quote causes error
   (message "some-variable is %s" some-variable))
;; ==> (boundp "less") ; "less" is not a variable. -> Error

Lispは、実際の変数(またはリスト、または関数名)が渡されるように、評価を妨げているフォームを引用することにより、到達したフォームを評価します。


ありがとう!あなたの答えは、両方のソースに飛び込んで、解決策を思い付くのに役立ちました。また、明確な例で質問を更新しました。
カウシャルモディ14年

6
これがopを助けてくれてうれしいですが、実際には質問に答えていません(同じ質問をしている他の人に役立つように)。あなたは、シンボルを引用する必要があるか、そうでなければ評価されることを説明するだけです。それがためのケースではありませんなぜあなたは説明していないbound-and-truepと私が使用しているとき引用しなければならないのなぜ疑問だったboundpが、使用しないときbound-and-truep
メガネザル

@tarsius私は実際にboundpシンボルを要求する(評価されていない)とbound-and-truep箇条書きの変数の値を必要とする(最初の答えの後に編集された)間の区別を含めます
ジョナサンリーチペピン

doc-stringがそう言うと言うだけでなく、なぜそうなのか(マクロは評価しないことを選ぶかもしれません)に言及することが不可欠だと思います。これは非常に良い質問だと思います。そのboundpとbound-and-true-pは一例です。質問が本当に要約するものは、評価ルールについて学びたいという欲求です。
メガネザル

@tarsiusこの回答で評価ルールは説明されていませんか?少なくとも引用だけを含む基本的なもの...あなたの答えは間違いなくより完全ですが、それはトピックをはるかに超えていますよね?
T.バーロン14年

16

関数以外の位置にあるシンボルは、変数の名前として扱われます。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)

そして、それが評価され、nilif 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関数として定義することができ、引数を引用符で囲む必要がありますが、マクロを気にする変数を使用して、'


驚くほどよく答えました。
チャールズリッチー

2

のソースコードからboundp

DEFUN ("boundp", Fboundp, Sboundp, 1, 1, 0,
      doc: /* Return t if SYMBOL's value is not void.
Note that if `lexical-binding' is in effect, this refers to the
global value outside of any lexical scope.  */)

boundpsymbol入力としてa が必要です。'some-variableは変数のシンボルですsome-variable

のソースコードから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))

bound-and-true-pvariable入力としてa が必要です。

bound-and-true-pマクロ内で、を実行してシンボルを取得し(quote ,var)ます。入力がの場合、結果はsome-variable(quote ,var)なります'some-variable

私は入力を与えるときしかし'some-variablebound-and-true-p、私はエラーを取得する:and: Wrong type argument: symbolp, (quote some-variable)マクロが(記号を期待されていないため、'some-variable入力時)。


ただヘッズアップ。''symbol ない意味をなします。という意味(quote (quote symbol))です。エラーが発生する理由は、それがの有効な引数ではないためですboundp
マラバルバ14年

@Malabarbaありがとう。修正しました。
カウシャルモディ14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.