Lambdaカクテル

Common LISPが好きなWeb屋さんです 自宅サーバやフロントエンドもできます

階乗の根っこはどこなのか

***※筆者はズブの文系です。その点覚悟してください。

階乗。それはプログラミングの初歩として良く再帰処理やループの例題として扱われる。
パターンマッチを使った階乗の記法はとても美しい。

が。ここで疑問が残る。
階乗は再帰処理を用いて表記するのだが、特に関数型言語での再帰処理は、その再帰の終着点を指示することになる。
階乗では特に、

fact :: Int->Int
fact 0 = 1
fact n = n * fact (n - 1)
(define fact
 (lambda (n)
  (if (eqv? n 0) 1 (* n (fact (- n 1))))))

このようにfact 0が1であることを教えている。
でも、これってfact 1 = 1でもいいんじゃない?
階乗は自然数にしか適用しない*1はずなので、fact 0はそもそも存在しないはずだ。*2
そういうわけで、僕はfactの根っこは1にするし、それで障害が起こったことはない。だってfact 1 = 1だもん。
また、再帰が一回稼げるからちょこっとだけ速度が速くなるような気がする。
fact 0は定義できるのだけれど、再帰処理で利用する価値がないので無用だと思うんだけど。

*1:Γ関数は階乗の操作を拡張し、その定義を実数に拡大してある。

*2:0を自然数の仲間に入れるかは長いこと議論の対象となっている。しかし初等教育では自然数は1から始まるものとされる