Next: , Previous: Accessing Variables, Up: Variables


10.8 変数値の変更

変数の値を変更する普通の方法は、スペシャルフォームsetqを使うことです。 実行時に選択する変数を計算する必要があるときには、 関数setを使います。

— Special Form: setq [symbol form]...

このスペシャルフォームは、変数の値を変更するもっとも一般的な方法である。 各symbolに、対応するformの評価結果である新たな値を与える。 シンボルの既存の際、ローカルの束縛を変更する。

setqsymbolを評価しない。 読者が書いたシンボルに設定する。 この変数は自動的にクォートされるのである。 setqの‘q’は、『quoted(クォートする)』を表す。

フォームsetqの値は、最後のformの値である。

          (setq x (1+ 2))
               ⇒ 3
          
          x                   ; xはグローバル値を持つ
               ⇒ 3
          (let ((x 5))
          
            (setq x 6)        ; xのローカル束縛を設定する
            x)
               ⇒ 6
          
          x                   ; グローバル値は変更されない
               ⇒ 3

最初のformを評価して最初のsymbolに設定し、 つぎに、2番目のformを評価して2番目のsymbolに設定し、 といった具合になることに注意。

          
          
          (setq x 10          ; xは、yの値を計算するまえに
                y (1+ x))     ;   設定されることに注意
               ⇒ 11
— Function: set symbol value

この関数は、symbolの値としてvalueを設定し、valueを返す。 setは関数なので、symbolとして書いた式は、 設定するシンボルを得るために評価される。

変数の既存の最ローカルの束縛に設定する。 隠されている束縛には影響しない。

          (set one 1)
          error--> Symbol's value as variable is void: one
          (set 'one 1)
               ⇒ 1
          (set 'two 'one)
               ⇒ one
          
          (set two 2)         ; twoはシンボルoneに評価される
               ⇒ 2
          
          one                 ; そのため、oneに設定される
               ⇒ 2
          
          
          (let ((one 1))      ; oneのこの束縛が設定され、
            (set 'one 3)      ;   グローバル値は設定されない
            one)
               ⇒ 3
          one
               ⇒ 2

symbol(の評価結果)が実際にはシンボルでないと、 エラーwrong-type-argumentを通知する。

          (set '(x y) 'z)
          error--> Wrong type argument: symbolp, (x y)

論理的には、setsetqよりもさらに基本的な操作である。 どんなsetqの使い方でも、setで素直に書き直せる。 setqは、setを使ってマクロとして定義することも可能である。 しかし、setそのものを使うことは稀であり、 初心者はsetを知る必要がほとんどない。 設定する変数を実行時に選ぶときにのみ有用である。 たとえば、コマンドset-variableは、 ユーザーから変数名を読み取りその変数に設定するので、 setを使う必要がある。

Common Lispに関した注意: Common Lispでは、setはつねにシンボルの『スペシャル』な、つまり、 動的な値を変更し、文脈上の束縛を無視する。 Emacs Lispでは、すべての変数とすべての束縛は動的であり、 setはつねに既存の最ローカルの束縛に作用する。

変数に設定する別の関数は、リストに既存でない要素を追加するように 設計されたものです。

— Function: add-to-list symbol element

この関数は、elementが変数symbolの値のリストのメンバでなければ、 elementと変数symbolの値をコンスした値を 変数symbolに設定する。 リストを変更してもしなくても結果のリストを返す。 呼び出すまえに、symbolの値はリストであるほうがよい。

引数symbolは暗黙にクォートされない。 add-to-listは、setのように普通の関数であり、 setqとは違う。 必要ならば、読者自身でクォートする。

add-to-listの使い方を以下に示します。

     (setq foo '(a b))
          ⇒ (a b)
     
     
     (add-to-list 'foo 'c)     ;; cを追加する
          ⇒ (c a b)
     
     
     (add-to-list 'foo 'b)     ;; なんの効果もない
          ⇒ (c a b)
     
     
     foo                       ;; fooは変更されている
          ⇒ (c a b)

(add-to-list 'var value)に等価な式はつぎのとおりです。

     (or (member value var)
         (setq var (cons value var)))