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)
(-2)
(var2 init-form
...
(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)
(-2)
(var2 init-form
...
(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
が使われるので、 宣言の型に違反しています。
なし。
なし。
なし。