トップ «前の日記(2008-01-04) 最新 次の日記(2008-01-07)» 編集

Route 477



2008-01-06

[biwascheme] letrecとletrec*

3行でまとめると

  • letrecは相互再帰関数を定義するためのlet
  • letrec*はトップレベルの意味を明確にするために導入されたもの
  • letrec*はバインディングの値部分で、それより前の変数を参照してよい。letrecはダメ

ということみたい。

letrec*はR6RSで正式導入されたものなので、R5RSにはない。

以下R6RSのてきとーな概訳:

11.4 - letrec

  • (letrec <bindings> <body>) syntax
    • <bindings> は ((<variable1> <init1>) ...), initは式
    • <body>は11.3で説明されている
    • variableには同じ変数が複数回出てきてはいけない
  1. 各variableが新しい場所に束縛される
  2. その環境下で、各initが評価される(順序は不定)
  3. 各variableが対応したinitの評価結果に束縛される
  4. その環境下で、bodyが評価される
  5. body中の最後の式の評価結果が返される

各variableの有効範囲はletrec式の全体であり、これによって相互再帰関数を定義することができる。

(letrec ((even?
          (lambda (n)
            (if (zero? n)
                #t
                (odd? (- n 1)))))
         (odd?
          (lambda (n)
            (if (zero? n)
                #f
                (even? (- n 1))))))
  (even? 88))   
                        ⇒  #t

各initは、どのvariableの値も代入・参照することなしに評価できるべきである。 letrecの最もよくある使い方においては、全てのinitはlambda式なので、この条件は自動的に満たされる。 また、各initの継続は一度以上実行されるべきではない。

処理系の責任:処理系は、initの評価中にvariableが参照されたことを検出しなければならない。もし処理系がこのような違反を検出したなら、 例外&assertionを投げるべきである。initの継続が2回以上呼び出されたかどうかは、検出してもしなくても良い。が、検出するならば 例外&assertionを投げなければいけない。

11.4 - letrec*

  • (letrec* <bindings> <body>)
    • <bindings>は((<variable1> <init1>) ...), initは式、<body>は11.3参照。各variableは被っちゃダメ
  • 各variableが新しい場所に束縛される
  1. 各variableが左から順に、対応したinitの評価結果に束縛される
  2. この環境下でbodyが評価され、bodyの最後の式の評価結果が返される

評価・代入は左から順に行うが、各variableの束縛自体はletrec*式全体で有効であり、これによって相互再帰関数が定義できる。

(letrec* ((p
           (lambda (x)
             (+ 1 (q (- x 1)))))
          (q
           (lambda (y)
             (if (zero? y)
                 0
                 (+ 1 (p (- y 1))))))
          (x (p 5))
          (y x))
  y)
                        ⇒  5

各initは対応するvariableや、それ以降のvariableの値を参照・代入することなしに評価できなければならない。 また、各initの継続は2度以上実行されるべきではない。

処理系の責任:処理系はinitの評価中に、対応するvariableやそれ以降のvariableの値の参照を検出しなければならない。検出したら、 例外&assertionを投げなければならない。継続の方はチェックしてもしなくてもいいが、するなら例外&assertionを投げなければならない。