npt-japanese

% Special-Operator LET, LET*

UP


Special-Operator LET, LET*

Special Operator LET, LET*

構文

let ({var | (var [init-form])}*) declaration* form* => result*
let* ({var | (var [init-form])}*) declaration* form* => result*

引数と戻り値

var - シンボル
init-form - フォーム
declaration - 宣言式、評価はされません。
form - フォーム
result - formの返却値

定義

letlet*は、 新しい変数の束縛を作成し、 それらの束縛を使用した一連のformを実行します。 letは束縛を並行して行い、 let*はそれらを連続で行います。

次のフォームは、

(let ((var1 init-form-1)
      (var2 init-form-2)
      ...
      (varm init-form-m))
  declaration1
  declaration2
  ...
  declarationp
  form1
  form2
  ...
  formn)

最初に式init-form-1, init-form-2, …, をこの順番で評価し、返却値を保存します。 そのあと、全ての変数varjに対応する値を束縛します。 各束縛はレキシカルに行われますが、 special宣言があるときは逆になります。 formkの式はその順番で評価されます。 最後以外のすべての値は無視されます。 (つまりletのボディ部は、暗黙のprognです)

let*letに似ていますが、 変数の束縛が並行ではなく、 連続に行われるところが違っています。 let*では、 varinit-formの式は、 前に束縛されたvarsを参照することができます。

次のフォームは、

(let* ((var1 init-form-1)
       (var2 init-form-2)
       ...
       (varm init-form-m))
  declaration1
  declaration2
  ...
  declarationp
  form1
  form2
  ...
  formn)

最初にinit-form-1を評価し、 そのあとvar1にその値を束縛し、 そのあとinit-form-2を評価し、 そのあとvar2にその値を束縛し、 くり返します。 formkの式はその順番で評価されます。 最後以外のすべての値は無視されます。 (つまりlet*のボディ部は、暗黙のprognです)

letlet*の両方は、 もしvarに関連するinit-formが無かったときは、 varnilで初期化されます。

特殊フォームのletは、 どんな初期化フォームも 名前の束縛のスコープに含まれないという性質があります。 let*の変数のスコープは、 それ以降の変数の束縛には残りの初期値フォームが含まれます。

例文

(setq a 'top) =>  TOP
(defun dummy-function () a) =>  DUMMY-FUNCTION
(let ((a 'inside) (b a))
   (format nil "~S ~S ~S" a b (dummy-function))) =>  "INSIDE TOP TOP" 
(let* ((a 'inside) (b a))
   (format nil "~S ~S ~S" a b (dummy-function))) =>  "INSIDE INSIDE TOP" 
(let ((a 'inside) (b a))
   (declare (special a))
   (format nil "~S ~S ~S" a b (dummy-function))) =>  "INSIDE TOP INSIDE"

次のコードは正しくありません。

(let (x)
  (declare (integer x))
  (setq x (gcd y z))
  ...)

xはそれが使用される前に実際に値は代入されますし、 その代入される値は宣言された整数の型ですが、 xが初期化されるときにnilが使われるので、 宣言の型に違反しています。

影響

なし。

例外

なし。

参考

progv

備考

なし。


TOP, Github