and-let*

8章4節、and-let*に関して。
条件式が#fじゃなければその値を使って計算して、その結果で真偽を判定して、#fならば処理を止め、#f以外ならばさらにその値を使って計算して...、みたいな場合、つまり

int val1=0,val2=0,val3=0;
if ((0 != (val1 = SomeFunc1())) &&
    (0 != (val2 = SomeFunc2(val1))) &&
    (0 != (val3 = SomeFunc3(val1, val2))))
{
  SomeFunc4(val3);
}

みたいなコードを書こうとしたら、

(let ((val1 (SomeFunc1)))
  (if val1
    (let ((val2 (SomeFunc2 val1)))
      (if val2
        (let ((val3 (SomeFunc3 val1 val2)))
          (if val3
            (SomeFunc4 val3)))))))

とか

(cond ((SomeFunc1)
      => (lambda (val1)
           (cond ((SomeFunc2 val1)
                 => (lambda (val2)
                      (cond ((SomeFunc3 val1 val2)
                            => (lambda (val3)
                                 (cond (val3 (SomeFunc4 val3)))))))))

みたいに、すぐインデントが深くなって読みにくい!


ってことで、「名前を束縛しつつandみたいにどこかで#fが出たら処理を打ちきる」ための方法がand-let*。

(and-let* ((名前1 S式1)
           (名前2 S式2)
           ...
           (名前n S式n))
  本体のS式)

S式1から順に、評価してはその値で名前を束縛していって、n個全部が#f以外の値だったら「本体のS式」を評価して返す。
S式1〜S式nのうち、どれが#fになったら、ただちに#fを返す。

(名前i S式i)

の部分は、

(S式i)

やら

名前i

ともできて、前者は名前を束縛せずに真偽だけを判定する方法。
後者は変数の値が#fでない場合に処理を続行する方法。