Perlって末尾再帰の最適化ってやってるの?
30分プログラム、その549。Perlって末尾再帰の最適化ってやっているかを調べようとしてみた。
結論としては、よく分からない。普通の再帰もなかなかスタックオーバーフローで落ちないし、使用しているメモリ量で比較しようとしたけど、メモリ量を取得するうまい方法が見つからない。Devel::Sizeとかは変数の使用メモリ量だし。
とりあえず、末尾再帰だろうと、なかろうと
Deep recursion on subroutine "main::fact" at tail-rec.pl line 25.
という警告がでるので、最適化はしてないんだろう、たぶん。
goto &NAMEなる謎の演算子を使ってやれば、手動で最適化できる。すくなくとも上記の警告はでない。
sub fact_goto($$){ my ($i,$n) = @_; if($n == 0){ return $i; }else{ @_ = ($i*$n,$n-1); goto &fact_goto; } }
ソースコード
#! /usr/bin/perl # -*- mode:perl; coding:utf-8 -*- # # tail-rec.pl - # # Copyright(C) 2009 by mzp # Author: MIZUNO Hiroki / mzpppp at gmail dot com # http://howdyworld.org # # Timestamp: 2009/03/20 22:23:32 # # This program is free software; you can redistribute it and/or # modify it under MIT Lincence. # use strict; use warnings; use Devel::StackTrace; sub fact($){ my ($n) = @_; if($n == 0){ 1; }else{ $n * &fact($n-1); } } sub fact_iter($$){ my ($i,$n) = @_; if($n == 0){ return $i; }else{ &fact_iter($i*$n,$n-1,); } } sub fact_goto($$){ my ($i,$n) = @_; if($n == 0){ return $i; }else{ @_ = ($i*$n,$n-1); goto &fact_goto; } } fact(100); fact_iter(1,100); fact_goto(1,100);