Macro PROG, PROG*

UP


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による明示的な返却のときは転送された返却値。

定義

progprog*によって 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へ制御を移すときに使うことができます。 tagstatementにラベル付けされます。

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は、blocklettagbodyの語を用いて 下記のように説明することができます。

(prog variable-list declaration . body)
   ==  (block nil (let variable-list declaration (tagbody . body)))

TOP, Github