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