npt-japanese

% Declaration SPECIAL

UP


Declaration SPECIAL

Declaration SPECIAL

構文

(special var*)

引数

var - シンボル

有効な文脈

declareproclaim

影響する束縛の型

変数

定義

全てのvarという名前のものを動的に指定します。 この指定子は変数の束縛と参照に影響します。 全ての影響があった束縛変数は動的束縛になり、 変数参照は現在の動的束縛を参照します。 下記に例を示します。

(defun hack (thing *mod*)    ;束縛されたパラメーター*mod*は
  (declare (special *mod*))  ;hack1からも見ることができます。
  (hack1 (car thing)))       ;しかしthingはそうではありません。
(defun hack1 (arg)
  (declare (special *mod*))  ;hack1内の宣言*mod*は
                             ;specialで参照されます。
  (if (atom arg) *mod*
      (cons (hack1 (car arg)) (hack1 (cdr arg)))))

special宣言は、varの束縛の中では影響しません。 束縛内では暗黙的にspecial宣言がシャドウします。 そして明示的にspecialとして再宣言する必要があります。 special宣言は決して関数束縛に適用しません。

special宣言は境界宣言として利用可能であり、 束縛と参照の両方に影響します。 他には自由宣言も利用可能であり、これは参照のみに影響し、 変数の束縛に付随する宣言に依存します。

proclaimが使用されたとき、special宣言指定子は その変数の全ての束縛と参照に適用されます。 例えば次の通り。

(declaim (special x))

この例文の後で次のような関数帝があったとします。

(defun example (x) ...)

このときパラメーターxは レキシカル変数ではなく動的変数として束縛されます。

例文

(defun declare-eg (y)                  ;このyはspecialです
  (declare (special y))
  (let ((y t))                         ;このyはレキシカルでs
       (list y
             (locally (declare (special y)) y)))) ;このyの参照先は
                                                  ;special束縛のyです
=>  DECLARE-EG 
(declare-eg nil) =>  (T NIL) 
(setf (symbol-value 'x) 6)
(defun foo (x)                         ;xはレキシカル束縛
  (print x)
  (let ((x (1+ x)))                    ;xはspecial束縛であり
    (declare (special x))              ;レキシカル参照
    (bar))
  (1+ x))
(defun bar () 
  (print (locally (declare (special x))
           x)))
(foo 10) 
>>  10
>>  11
=>  11
(setf (symbol-value 'x) 6)
(defun bar (x y)            ;[1] 1回目のxの出現
  (let ((old-x x)           ;[2] 2回目のxの出現 -- 1回目と同じ
        (x y))              ;[3] 3回目のxの出現
    (declare (special x))
    (list old-x x)))
(bar 'first 'second) =>  (FIRST SECOND)
 (defun few (x &optional (y *foo*))
   (declare (special *foo*))
   ...)

この例の最初の行にある*foo*の参照は、 2行目にspecial宣言があるにもかかわらず、 1行目はspecialではありません。

(declaim (special prosp)) => 実装依存
(setq prosp 1 reg 1) =>  1
(let ((prosp 2) (reg 2))         ;prospの束縛は前のdeclaimにより
   (set 'prosp 3) (set 'reg 3)   ;specialになります。
   (list prosp reg))             ;reg変数はレキシカルです。
=>  (3 2)
(list prosp reg) =>  (1 3)

(declaim (special x))          ;xは常にspecialです。
(defun example (x y)                                 
  (declare (special y))
  (let ((y 3) (x (* x 2)))
    (print (+ y (locally (declare (special y)) y)))
    (let ((y 4)) (declare (special y)) (foo x)))) =>  EXAMPLE

上記のねじ曲がったコードは、 最も外側と最も内側のyの束縛は動的であり、 しかし中間の束縛はレキシカルです。 +の2つの引数は違っており、 1つ目はレキシカル変数yの値3で、 もうひとつは動的変数yです (この束縛は偶然にも外側のレベルでレキシカルに囲まれているものです)。 しかしながらproclamationによってxが常にspecialなので、 全てのxの束縛とxの参照は動的です。

参考

defparameter, defvar


TOP, Github