末尾再帰

再帰的な関数やプロシージャにおいて、自身の再帰呼び出しが、その計算における最後のステップになっているような再帰のパターン

[1][1]GOTO#[1]

手続き型言語と末尾再帰

編集

C

プログラムの手動変換

編集




{ 変換前 }
function F (a1:T1, a2:T2, ..., an:Tn) : T0
begin
   P ;
   return func (b1, b2, ..., bn) ;
end ;

{ 変換後 }
function F (a1:T1, a2:T2, ..., an:Tn) : T0
begin
   loop
     P ;
     a1 := b1 ;
     a2 := b2 ;
         :
     an := bn ;
   end loop ;
end ;

{
Ti は型P は手続きbi は値または a1an に対する副作用を伴わない式である
それ以外の識別子は変数を表すPの中に最低1個のreturn文がないと
スタックオーバーフローあるいは無限ループになる
}

関数型言語と末尾再帰

編集

使Scheme[2]





Common Lisp 
(defun fact (n)
  (labels ((ifact (n r)
             (if (= n 0)
                 r
                 (ifact (- n 1) (* n r)))))
    (ifact n 1)))

F#での末尾再帰の例:

// 非末尾再帰
let rec fact n =
  if n = 0 then 1 else fact (n - 1) * n

// 末尾再帰
let fact n =
  let rec ifact n r =
    if n = 0 then r else ifact (n - 1) (n * r)
  ifact n 1

末尾行では定義と同型の式が現れている。

末尾呼出し最適化

編集

: tail call optimization[3]



GOTO return Scheme 

SchemeC

注釈

編集
  1. ^ : tail call
  2. ^ : properly tail-recursive
  3. ^ : tail call elimination

出典

編集
  1. ^ a b bit 編集部『bit 単語帳』共立出版、1990年8月15日、147頁。ISBN 4-320-02526-1 

関連項目

編集