% Macro PROG, PROG*
Macro PROG
, PROG*
prog
({
var |
(var [init-form])}
*)
declaration* {
tag |
statement}
*
=> result*
prog*
({
var |
(var [init-form])}
*)
declaration* {
tag |
statement}
*
=> result*
var - 変数名
init-form - フォーム
declaration - 宣言式。評価されません。
tag - go
タグ。評価されません。
statement - compound-form。下記の説明に従って評価されます。
result - 通常の返却のときはnil
、
そうではなくreturn-from
による明示的な返却のときは転送された返却値。
prog
とprog*
によって
3つの異なった操作が実行されます。
それは、ローカル変数の束縛と、
return
構文の使用の許可と、
go
構文の使用の許可です。
典型的なprog
の見た目は次のようになります。
(prog (var1 var2 (var3 init-form-3) var4 (var5 init-form-5))
declaration*
statement1
tag1
statement2
statement3
statement4
tag2
statement5
...
)
prog
では、
最初に各init-formが指定された順に評価されます。
そのあとvarが対応する値と並列に束縛されます。
もしvarに対してinit-formが存在しないとき、
そのvarにはnil
が束縛されます。
prog
のボディ部は
それがtagbody
フォームであるかのように実行されます。
go
構文はtagへ制御を移すときに使うことができます。
tagはstatementにラベル付けされます。
prog
は暗黙に、prog
フォーム全体を囲うようにして、
nil
というblock
が確立しており、
return
を使ってprog
フォームからいつでも退出できます。
prog*
とprog
の違いは、
prog*
はvarの束縛と初期化は連続的に行われ、
各変数のinit-formの値は、以前の変数の値によって使用することができます。
(prog* ((y z) (x (car y)))
(return x))
上記はz
の値のcar
を返却します。
(setq a 1) => 1
(prog ((a 2) (b a)) (return (if (= a b) '= '/=))) => /=
(prog* ((a 2) (b a)) (return (if (= a b) '= '/=))) => =
(prog () 'no-return-value) => NIL
(defun king-of-confusion (w)
"Take a cons of two lists and make a list of conses.
Think of this function as being like a zipper."
(prog (x y z) ;Initialize x, y, z to NIL
(setq y (car w) z (cdr w))
loop
(cond ((null y) (return x))
((null z) (go err)))
rejoin
(setq x (cons (cons (car y) (car z)) x))
(setq y (cdr y) z (cdr z))
(go loop)
err
(cerror "Will self-pair extraneous items"
"Mismatch - gleep! ~S" y)
(setq z y)
(go rejoin))) => KING-OF-CONFUSION
これは下記に示すように、より明確に達成できます。
(defun prince-of-clarity (w)
"Take a cons of two lists and make a list of conses.
Think of this function as being like a zipper."
(do ((y (car w) (cdr y))
(z (cdr w) (cdr z))
(x '() (cons (cons (car y) (car z)) x)))
((null y) x)
(when (null z)
(cerror "Will self-pair extraneous items"
"Mismatch - gleep! ~S" y)
(setq z y)))) => PRINCE-OF-CLARITY
なし。
なし。
block
,
let
,
tagbody
,
go
,
return
,
3.1. 評価
prog
は、block
とlet
とtagbody
の語を用いて
下記のように説明することができます。
(prog variable-list declaration . body)
== (block nil (let variable-list declaration (tagbody . body)))