% 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の返却値
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が使われるので、
宣言の型に違反しています。
なし。
なし。
なし。