次の関数は再帰的な関数だ。

( define fact ( lambda ( n ) ( if ( = n 0 ) 1 ( * n ( fact ( - n 1 ))))))

この関数は内部で自分自身を呼び出しているので、普通の方法では無名関数として定義できない。

こういう場合、不動点オペレータというものを使うと以下のようにしてfactを定義することができる。（fact関数の中で直接factという名前を使っていない所がポイント）

( define fact ( let (( Y ( lambda ( F ) (( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))) ( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))))))) ( Y ( lambda ( f ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n ( f ( - n 1 )))))))))

ここで天下り的に出てきたYをなんとか導出してみたいと思って数日間考えていたのだが、ようやく方法が分かった。ほとんどは最後に挙げた参考URLに書いてあることの焼き直し。

まず、こういう関数を考えてみる。

( define fact-maker ( lambda ( s ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n (( s s ) ( - n 1 )))))))

すると以下のような変形ができるので、

( fact-maker fact-maker ) (( lambda ( s ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n (( s s ) ( - n 1 )))))) fact-maker ) ( let (( s fact-maker )) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n (( s s ) ( - n 1 )))))) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n (( fact-maker fact-maker ) ( - n 1 )))))

(fact-maker fact-maker)はfactに等しい。

次に、fact-makerを変形していく。

( define fact-maker ( lambda ( s ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n (( s s ) ( - n 1 ))))))) ( define fact-maker ( lambda ( s ) ( let (( f ( lambda ( x ) (( s s ) x )))) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n ( f ( - n 1 )))))))) ( define fact-maker ( lambda ( s ) (( lambda ( f ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n ( f ( - n 1 )))))) ( lambda ( x ) (( s s ) x ))))) ( define fact-maker ( lambda ( s ) ( F ( lambda ( x ) (( s s ) x ))))) ( define F ( lambda ( f ) ( lambda ( n ) ( if ( = n 0 ) 1 ( * n ( f ( - n 1 )))))))

これを使うと、(fact-maker fact-maker)は以下のような式に展開される。

(( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))) ( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))))

ここからFを抽象してYが得られる。

( define Y ( lambda ( F ) (( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))) ( lambda ( s ) ( F ( lambda ( x ) (( s s ) x )))))))

以上のことをまとめると、

(Y F) == (fact-maker fact-maker) == fact

となる。