« Pythonで階乗を求める(これはすこしまし?) |Main| ブログにコードを貼り付ける方法.js alpha0.1 »

« Pythonで階乗を求める(これはすこしまし?) | Python | パラメータを取るデコレータ »

Pythonで階乗を求める(Yコンビネータ編)

Q: 「Pythonで階乗を求める(これはひどい)」はYコンビネータ?

A: いいえ。

再帰呼び出しは普通、以下のように関数が自分自身の名前を使って自分自身を呼び出します。

>>> f = lambda n: n and n * f(n - 1) or 1
>>> f(5)
120

ここで、名前をつけずに、関数自体にも手を加えずに、再帰呼び出しを実現するための手段がYコンビネータです。再帰呼び出しを実現するだけならばYコンビネータは必須ではありません。 前回のコードはYコンビネータを使わずに再帰呼び出しをしています。具体的には、元の関数をnだけを受け取るのではなく、自分自身も引数fに受け取るようにし、また再帰呼び出しでfを呼び出す際にも引数にfを渡してやるようにしています。

Yコンビネータ版は以下。

>>> Y = lambda f:((lambda g: f(lambda x: g(g)(x)))
	          (lambda g: f(lambda x: g(g)(x))))
>>> lambda f: lambda n: n and n * f(n - 1) or 1
<function <lambda> at 0x011DF9B0>
>>> Y(_)
<function <lambda> at 0x011EB770>
>>> _(6)
720
>>> (lambda f:((lambda g: f(lambda x: g(g)(x)))(lambda g: f(lambda x: g(g)(x)))))
(lambda f: lambda n: n and n * f(n - 1) or 1)(6)
720
「lambda n: n and n * f(n - 1) or 1」がそのまま手を加えられずに使われている(lambda f:~で囲われているだけ)というところがポイントです。前回の「lambda f,x:x and f(f,x-1)*x or 1」は引数を追加してしまっています。

トラックバック(Trackback)

Trackback URL: http://www.nishiohirokazu.org/mt/mt-tb.cgi/367

ご意見・ご感想をお送りください(フィードバック)

(フィードバックはメールで送信され、基本的に表示されませんが、内容によっては公開させていただくこともございます。ご了承ください。Your comment doesn't appear the page immediately. If the comment has value to other people, it will be put on the page or subsequent entries. Thank you.)

上の情報は、いずれも未記入でかまいません。 All of above questions are optional.