ローカル変数

  • let
  • let*
  • letrec

の3つのタイプがあるそうだ。
使い方は全部同じで

(let族 ((変数1 変数1を初期化するS式)
        (変数2 変数2を初期化するS式)
        ...
        (変数n 変数nを初期化するS式))
       let族の値となるS式)

ってな感じ。
「let族の値となるS式」の中で「変数1」〜「変数n」を使用可能。
(「let族」はlet、let*、letrecのこと)

let

一番基本的なやつ。
「変数iを初期化するS式」が評価され、その値が名前「変数i」を束縛する。
各「変数iを初期化するS式」が評価される順序は未定義だそうだ。

let*

letでは「変数iを初期化するS式」の評価される順序が未定義だったけど、上から順に評価するように保障したもの。
あと、「変数i」を「変数i+1を初期化するS式」〜「変数nを初期化するS式」内で使用できる。
つまり、

(let* ((x (some-function1))
       (y (some-function2 x)
       (z (some-function3 y))
      (some-function4 z))

(let ((x (some-function1)))
  (let ((y (some-function2 x)))
    (let ((z (some-function3 y)))
      (some-function4 z))))

のようにネストしたlet式と等価だと。

letrec

これは「変数iを初期化するS式」がlambda式で、そのlambda式の中で「変数1」〜「変数n」を参照したい場合に使う。
ってことで、要はローカルな再帰関数を作るためのもの(?)。

gosh> (letrec ((fact (lambda (n)
                       (if (= n 0)
                           1
                           (* n (fact (- n 1)))))))
              (fact 5))
120

単に再帰じゃなくて、相互再帰関数もOK。