R5RS 以前の letrec は実装に依存します。 R6RS でセマンティック・エラーになる書き方をしてみると……

( let (( a 4 ) ( b 5 )) ( list ( letrec (( a ( begin ( set! b 2 ) b )) ( b ( begin ( set! a 3 ) a )) ( f ( lambda ( t ) ( cons a b )))) ( f #t )) ( cons a b )))

letrec* は実装に依存しません。 これも、 R6RS でセマンティック・エラーになる書き方ですが……。

( let (( a 4 ) ( b 5 )) ( list ( letrec* (( a ( begin ( set! b 2 ) b )) ( b ( begin ( set! a 3 ) a )) ( f ( lambda ( t ) ( cons a b )))) ( f #t )) ( cons a b )))

この letrec* を使った式の評価結果は、 次のように書いた式と同じ評価結果になります。

( let (( a 4 ) ( b 5 )) ( list ( let (( a ' UNSPECIFIED ) ( b ' UNSPECIFIED ) ( f ' UNSPECIFIED )) ( set! a ( begin ( set! b 2 ) b )) ( set! b ( begin ( set! a 3 ) a )) ( set! f ( lambda ( t ) ( cons a b ))) ( f #t )) ( cons a b )))

letrec を letrec* の評価・束縛の順不同版と考えると、 b を a より先に評価・束縛する場合もありえます。

( let (( a 4 ) ( b 5 )) ( list ( letrec* (( f ( lambda ( t ) ( cons a b ))) ( b ( begin ( set! a 3 ) a )) ( a ( begin ( set! b 2 ) b ))) ( f #t )) ( cons a b )))

R7RS に従って、 letrec を中間変数を使って書くと評価順に依存しなくなり、 letrec* で得ることができない値になります。

( let (( a 4 ) ( b 5 )) ( list ( let (( a ' UNSPECIFIED ) ( b ' UNSPECIFIED ) ( f ' UNSPECIFIED ) ( t1 ' UNSPECIFIED ) ( t2 ' UNSPECIFIED ) ( t3 ' UNSPECIFIED )) ( set! t1 ( begin ( set! b 2 ) b )) ( set! t2 ( begin ( set! a 3 ) a )) ( set! t3 ( lambda ( t ) ( cons a b ))) ( set! a t1 ) ( set! b t2 ) ( set! f t3 ) ( f #t )) ( cons a b ))) ( let (( a 4 ) ( b 5 )) ( list ( let (( a ' UNSPECIFIED ) ( b ' UNSPECIFIED ) ( f ' UNSPECIFIED ) ( t1 ' UNSPECIFIED ) ( t2 ' UNSPECIFIED ) ( t3 ' UNSPECIFIED )) ( set! t3 ( lambda ( t ) ( cons a b ))) ( set! t2 ( begin ( set! a 3 ) a )) ( set! t1 ( begin ( set! b 2 ) b )) ( set! f t3 ) ( set! b t2 ) ( set! a t1 ) ( f #t )) ( cons a b )))