9

Common Lisp(SBCL 1.0.58)で、マクロORがgensymを使用するのに、ANDを使用しないのはなぜですか?

例えば、

    CL-USER> (macroexpand '(and 1 2 3 4 5))
    (IF 1
        (AND 2 3 4 5)
        NIL)
    T
    CL-USER> (macroexpand '(or 1 2 3 4 5))
    (LET ((#:G967 1))
      (IF #:G967
          #:G967
          (OR 2 3 4 5)))
    T
    CL-USER> 

マクロが定義されているdefboot.lispを調べましたが、コメントに関連するものは何も見つかりませんでした。

4

2 に答える 2

16

これは、実装された論理演算子が短絡し、最後に評価した形式によって生成された値を返すことを目的としているためです。

これを実現するために、を評価する最後のフォームが生成されるか、それ自体への最後の末尾呼び出しの結果になるため、andは必要ありません。gensymNIL

一方、評価orする最初の非値を返すNIL必要があるため、末尾呼び出しに依存することはできません。それがgensymないので、それを行う必要があります:

(IF 1
    1
    (OR 2 3 4 5))

1展開に2回表示されます。この場合、生成する式が2回1評価されることを意味します。そして、あなたはあなたのマクロでそれを決して望んでいません

于 2012-08-27T19:11:49.603 に答える
4

a偽であるとしましょうがb、、、cおよびdは真です。さて、短絡のために私達は持っています:

(or  a b c d) => b
(and a b c d) => nil
(or    b c d) => b
(and   b c d) => d

ご覧のとおり、このAND場合、左端の引数の値がフォームの戻り値として使用されることはありません(引数が1つしかない場合は、展開が異なります)。一方、このOR場合、左端の引数の値がtrueの場合は戻り値になります。したがって、AND値が真実かどうかをテストした後で値を破棄できます(したがって、一時変数に格納する必要はありません)が、破棄することはORできません。

于 2012-08-27T19:13:22.690 に答える