Hatena::ブログ(Diary)

Smalltalkのtは小文字です

id:sumim:about

Smalltalk を本格的に勉強する気はないけれど、うんちく程度に知っておきたいなら→Smalltalkをちょっとかじってみたい人のための、チュートリアルまとめ - Qiita

オブジェクト指向の“モヤッと”の正体を知りたくなったらこちらの記事が役に立つかも→id:sumim:20080415:p1 とか id:sumim:20040525:p1


 | 

2013-06-02

[] 再帰呼び出しを再帰呼び出しなしで実現 を Squeak Smalltalk



読者のみなさんにもgotoのある言語で試すことをオススメします。

再帰呼び出しを再帰呼び出しなしで実現 - 西尾泰和のはてなダイアリー

ということだったので goto も使える Squeak Smalltalk で書いてみました(違うw。


| VERBOSE stack functionResult showAny showMany total3 |
VERBOSE := true.
stack := OrderedCollection new.
functionResult := 0.

showMany := nil. "for compiler"

showAny := [:x |
   (x isKindOf: Integer) ifTrue: [
      Transcript show: x
   ] ifFalse: [
      showMany value: x
   ]
].

showMany := [:xs |
   Transcript show: '['.
   (1 to: xs size) do: [:i |
      showAny value: (xs at: i).
   ] separatedBy: [Transcript show: ', '].
   Transcript show: ']'
].

total3 := [:xs |
   | ENTRYPOINT result i LOOP x RETURNPOINT frame |
ENTRYPOINT := thisContext previousPc.
   result := 0.

   i := 0.
LOOP := thisContext previousPc.
   i := i + 1.
   x := xs at: i.

   VERBOSE ifTrue: [
      Transcript show: 'xs:'.
      showMany value: xs.
      Transcript show: ', x:'.
      showAny value: x.
      Transcript show: ', i:'; show: i; show: ', result:'; show: result; cr; endEntry.
   ].

   (x isKindOf: Integer) ifTrue: [
      result := result + x.
   ] ifFalse: [
      stack addFirst: {xs. i. x. result}.
      xs := x.
      RETURNPOINT := thisContext previousPc + 10.
      thisContext pc: ENTRYPOINT.

RETURNPOINT.
      frame := stack removeFirst.
      xs := frame first.
      i := frame second.
      x := frame third.
      result := frame last.

      result := result + functionResult
   ].
   i < xs size ifTrue: [thisContext pc: LOOP].

   stack isEmpty ifFalse: [
      functionResult := result.
      thisContext pc: RETURNPOINT.
   ].

   result
].

VERBOSE ifTrue: [World findATranscript: nil].
total3 value: #(1 (2 3) 4)  "=> 10 "
xs:[1, [2, 3], 4], x:1, i:1, result:0
xs:[1, [2, 3], 4], x:[2, 3], i:2, result:1
xs:[2, 3], x:2, i:1, result:0
xs:[2, 3], x:3, i:2, result:2
xs:[1, [2, 3], 4], x:4, i:3, result:6

goto の動作は簡単のため、戻ってきたい場所のプログラムカウンター(pc)をラベルに模した変数に保持し(LABEL := thisContext previousPc)、必要なときにその pc に飛ぶ(thisContext pc: LABEL)ことで実現しています。

しかしこの方法だと RETURNPOINT の pc は未通過のため保持できないので RETURNPOINT への代入については ENTRYPOINT に戻る前にオフセット値をハードコードして保持しなければならなかった点がちょっと心残りですね。^^;

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。

トラックバック - http://d.hatena.ne.jp/sumim/20130602/p1
 | 
2004 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 08 | 10 | 12 |
2013 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 11 | 12 |
2014 | 01 | 02 | 05 | 07 | 08 | 09 | 10 | 11 |
2015 | 04 | 07 | 08 | 11 | 12 |
2016 | 02 | 03 | 06 | 07 | 08 |
2017 | 04 | 05 | 06 |

最近のコメント

1. 06/28 sumim
2. 06/28 squeaker
3. 06/28 sumim
4. 06/28 squeaker
5. 06/25 sumim

最近のトラックバック

1. 05/25 プラグインレスでSVGを表示する「SIE」開発ブログ - メッセージをや...
2. 01/30 no_orz_no_life - Erlangとジャンケン
3. 12/31 檜山正幸のキマイラ飼育記 - J言語、だってぇー?
4. 09/04 Twitter / @atsushifx
5. 07/06 みねこあ - オブジェクト指向 と FizzBuzz

この日記のはてなブックマーク数
1718684