`setq-local`は何をしますか、そしていつそれを使うべきですか?


16

ここでSXですべてのドキュメントと多数の投稿を読んだ後でも、バッファローカル変数のすべてのバリエーションについては明確ではありません。

私の理解の概要は次のとおりです。

(defvar foo ..)ファイルの動的変数を宣言します。ただし、変数は(1)defvar ステートメントも含まれていない限り、他のファイルには認識されません。(2)変数はバッファーローカルではなくスコープ内でグローバルです。

(make-variable-buffer-local foo)defvar上記は、変数fooが設定されている場合、変数fooが設定されているすべての場所でバッファローカルとして扱われることをコンパイラと他のすべての人に伝えた後です。そのため、このパターンは、バッファローカル変数を宣言するのに適したスタイルであり、ファイルに両方のステートメントを連続して配置します。

(defvar xxx ...)                    ;declare xxx with global scope
(make-variable-buffer-local 'xxx)   ;but now make it buffer-local everywhere

便宜上、(defvar-local xxx ...)フォームは上記の2行の代わりに1行として使用できます。

(defvar-local xxx ...)       ;make xxx buffer local everywhere

上記のように宣言されると、変数xxxはsetqステートメントの他の変数と同様に使用できます。

既にグローバルダイナミック変数であるバッファローカル変数の単一のインスタンスが必要な場合は、次の宣言を使用します。最初のステートメントはグローバルスコープの動的変数を宣言し、2番目のステートメントはその変数のバッファーローカルバージョンのインスタンスを現在のバッファーに1つだけ作成します。

(defvar xxx ...)             ;declare xxx with global scope
(make-local-variable 'xxx)   ;make xxx local in this buffer only

さて、私の明示的な質問について(上記はすべて、私の理解が正しいかどうかに関する暗黙の質問でした)。

変数の値を設定するとき、setqまたは を使用できますsetq-local。いつsetq-local使用すべきですか?どうして?

setq-localバッファローカル変数または非バッファローカル変数で使用するとどうなりますか?

されるsetq-localために必要なdefvar-local宣言された変数?

ウィルsetq-local通常のdefvar宣言された変数はバッファローカル変数にそれを回しますか?(言い換えれば、setq-local何らかの形で(make-variable-local xxx)宣言と同等ですか?


余分な労力をありがとうスコット。ここから追加のバッククォートを入れます。–
ケビン

2
(setq-local VAR VALUE)は、の省略形です(set (make-local-variable VAR) VALUE)
ドリュー

回答:


18

ほとんどの仮定は近いものです。後でいくつか言及します。しかし、まず主な質問です。

フォームsetq-localは単に便利であり、make-local-variableその後にを続けるのと同じsetqです。C-h f setq-localドキュメントを表示するためにa を実行し、ソースまでクリックスルーした場合、これを見たかもしれません。それが私の第一印象を検証した方法です。ただし、make-local-variable実際には変数自体を返すなどの事実を最適化するため、コードは少しわかりにくくなっています。を使用するsetq-localと、一部のコードの局所性を示すことができるため、コードが変数のグローバルな値を使用できないことを他の人に知らせることができます。ローカル変数にアクセスするために使用する必要ありませ。任意の変数をバッファローカルにすることができ、変数に触れるすべてのコードに影響します(グローバルコピーを取得するなどの方法で障害が発生する場合を除くsetq-default)。

それが第一の答えです。さて、あなたの背景には少しずれていることがいくつかあります。あなたがそれについて尋ねたので、私はいくつかのことに対処します。

1つ目は「他のファイルには認識されない」です。これは本当ではありません。任意のコードは含めずに(彼らは「グローバル」と呼ばれている理由です)すべてのグローバル変数を参照することができますdefvar(とC-h f defvarそう言います)。実際、各グローバル変数に対してメイン(docstringおよびデフォルト値)が1つだけ存在する必要がありdefvarます。defvarちょうど変数名とは、バイトコンパイラの警告を抑制するために使用することができます。Emacsは、最初に表示された値のみを使用し¹、最後の値を使用します。defvarvalue / docstringのが複数ある場合、コードを読んでいる人を混乱させる可能性があります。そして、ファイルをロードする順序は重要です。

一部の変数は、バッファローカルとしてのみ使用すること目的としており、使用する変数ですdefvar-local(または、短い形式が追加される前の古いコードで主に使用される2つの部分defvar/ make-variable-buffer-local)。これにより、すべてのバッファでバッファローカルになります。一部の変数では、その主な用途はバッファローカルではありませんが、何らかの理由で、1つのバッファに異なる値を持たせたい場合があります。を使用するのはmake-local-variable、通常、いくつかのバッファセットアップコードでを使用した直後defvarです。

一般的なこととして、defvarフォームには2つの目的があります。1つはC-h v、他の人が変数の目的を知るために使用できるドキュメントを用意することです。2番目は、変数が常に設定されるように「デフォルト」値を宣言することです。デフォルト値の宣言は、変数のグローバル(またはデフォルト)インスタンスにのみ影響し、そのインスタンスがまだ何かに設定されていない場合にのみ使用されます。つまり、setq何らかの変数を使用してからファイルをdefvar(たとえば、aを介してrequire)含めた場合、defvarは値を変更しません。

¹ より正確にdefvarは、変数の値が既に設定されている場合は変更しません(ただし、docstringは設定します)。これは(setq some-variable)、パッケージのデフォルト値を上書きするためにパッケージがロードされる前にユーザーの初期化ファイルが実行できるようにするためのものです。


1
非常に明確な答えをありがとう、それは大いに役立つ。「他のファイルには知られていない」というフレーズを使用したとき、他のファイルはdefvarを追加しない限り変数は無料であると考えるため、無料の変数警告を考えていました。set-localローカル変数が設定されていることを読者に伝える文が好きです。コードの可読性を向上させるためにできることは何でも良いことです!PS。ソースへのクリックスルーをより頻繁に試みます。私の現在の開発レベルでは、セマンティクスに達していないことがよくあります... :
ケビン

1
defvarグローバル変数ごとに1つだけであるべきです」は厳密には正しくありません。そのVARNAMEの適切な定義(初期値と理想的にはdocstring)に関係(defvar VARNAME) なく、値なしで宣言する必要がある状況があります。
phils

2
また、setq-localand defvar-localはEmacs 24.3でのみ導入されたことにも注意してください。
phils

1
@phils、あなたが話している状況を特定してください、値なしでどこ(defvar varname)に宣言する必要がありますか?他の場所で宣言したグローバルについて、ファイル内の無料の変数警告を取り除く方法を尋ねていたときに、ドリューが別のスレッドで提案したことだと思っています。今やっています。それはあなたが話す状況ですか?
ケビン

1
1つの理由は、バイトコンパイルの警告を回避することC-h i g (elisp) Warning Tipsです(はい)。もう1つは、レキシカルバインディングを使用するライブラリ用で、変数がレキシカルバインドではなく動的にバインドされるようにします(必要な場合)。
phils
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.