id:sumim:20100910:p1 に絡めて、せっかくなら Smalltalk ならではの変わった方法もひとつ…とひねり出してみたのがこちら。
Integer >> fib | temp1 temp2 mine me sender | temp1 := 0. temp2 := 1. self > 1 ifTrue: [(self - 1) fib]. mine := temp1 + temp2. me := thisContext method. sender := thisContext sender. sender method == me ifTrue: [sender tempAt: 2 put: mine]. sender sender method == me ifTrue: [sender sender tempAt: 1 put: mine]. ^mine
[1000 fib] timeToRun "=> 3 ms "
二個手前までの実行時コンテキスト(スタックフレーム)をたぐって、それぞれ(一つ前のコンテキストでは二つ目の、二つ前のコンテキストでは一つ目の)一次変数を書き換え、その和をもって返値としています。再帰をしている((self-1) fib のコール)のに、その返値は使っていない―というところで再帰の副作用しか使っていないことが(Smalltalk が読めなくてもなんとなく)おわかりいただけると思います。
Smalltalk ならでは―とか言いつつ、おそらく Ruby(の特に MatzRuby)以外であれば、今時の動的な言語ならできるはずです(実はよく調べないで書いているのですが、動的言語を名乗るからには、このくらいは出来て欲しいという期待を込めて^^;)。