末尾呼出と可変長引数とlet-optionals*

ふと思ったんだけど、階乗とかで末尾再帰をさせようと

(define (fact n)
	(define (loop n v)
	  (if (<= n 1) v
	      (loop (- n 1) (* v n))))
	(loop n 1))

のよーに内部関数作っていたのって可変長引数使えば

(define (fact n . opt)
  (let-optionals* opt ((v 1))
  (if (<= n 1) v
      (fact (- n 1) (* v n)))))

内部引数関数いらなくなる。うまいかも。
どっちが速いかは微妙かな。暇見てチェックしよっと。

追記:なんかぼけてて「内部引数」とか書いてた。修正。

gosh> (begin (time (fact-original 50000)) 0)
;(time (fact-original 50000))
; real  29.076
; user  28.050
; sys    0.030
0
gosh> (begin (time (fact-variable 50000)) 0)
;(time (fact-variable 50000))
; real  29.884
; user  28.110
; sys    0.030
0

やっぱあんまりかわんないか。

追記2:
shiroさんからのツッコミ(ありがたや)。

shiro 2008/10/22 16:52
それはたぶん計算時間のほとんどが多倍長整数演算に費やされているので他の要因による差が見えないだけだと思います。
sumくらいでやってみてください。

確かに・・・試してみる。

gosh> (time (sum-variable 50000))
;(time (sum-variable 50000))
; real   0.022
; user   0.020
; sys    0.000
1250025000
gosh> (time (sum-original 50000))
;(time (sum-original 50000))
; real   0.013
; user   0.010
; sys    0.000
1250025000

本当だ。かなり違う。やはり余計なリスト走査と毎回lambda構築(環境構築)が入る分なのかな。中を少し読みはじめてるので、勉強がてら後でまじめに考えてみるつもり。
#と書くといつも怠け心が出てあうとなのだよな。。。