まず素直に #ifTrue:ifFalse: を使った条件分岐で。関数なのでクラスは定義せずブロック(無名関数)を使います。
| ack | ack := nil. ack := [:m :n | m = 0 ifTrue: [ n + 1 ] ifFalse: [ n = 0 ifTrue: [ ack value: m - 1 value: 1 ] ifFalse: [ ack value: m - 1 value: (ack value: m value: n - 1) ] ] ]. ack value: 3 value: 4. "=> 125 "
if のネストがちょっとイヤ〜ンな感じなので #caseOf:otherwise: を使ってすっきりさせます。true にメッセージを送るのはバッドノウハウです。^^;
| ack | ack := [:m :n | true caseOf: { [m = 0] -> [n + 1]. [n = 0] -> [ack value: m - 1 value: 1]. } otherwise: [ack value: m - 1 value: (ack value: m value: n - 1)] ]. ack value: 3 value: 4. "=> 125 "
このままだと ack(4,1) もままならないので、メモ化をします。
| ack memo | memo := Dictionary new. ack := nil. ack := [:m :n | memo at: {m. n} ifAbsentPut: [ true caseOf: { [m = 0] -> [n + 1]. [n = 0] -> [ack value: m - 1 value: 1]. } otherwise: [ack value: m - 1 value: (ack value: m value: n - 1)] ] ]. ack value: 3 value: 4. "=> 125 " ack value: 4 value: 1. "=> 65533 "
それでも ack(4.2) だとしばらくはがんばりますが結局落ちてしまうようです(2 GHz Core i7, OS X 向け CogVM 使用)。残念。