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の返却値
letとlet*は、 新しい変数の束縛を作成し、 それらの束縛を使用した一連の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*では、 varのinit-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です)
letとlet*の両方は、 もしvarに関連するinit-formが無かったときは、 varはnilで初期化されます。
特殊フォームの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が使われるので、 宣言の型に違反しています。
なし。
なし。
なし。