カウンターで練習してみる

動かない

C.ioとして、下記ファイルを保存。

C := Object clone do (
 n := 1
 count := method(n := n + 1)
 asString := n asString 
)

c := C clone

コマンドラインから使ってみる。

Io> doFile("C.io")
==> 1
Io> c
==> 1
Io> c count
==> 2
Io> c
==> 1
Io> c n
==> 1

動かない。

上記定義では、"n + 1"でいう"n"は"c n"を参照するが、左側の"n"はメソッド実行時に新たに生成されるローカルオブジェクトにスロットnを作成して、"n + 1"をセットする。だから、カウントアップされたnはローカルオブジェクトにのみ保存され、メソッド終了と共に捨てられる。結果、"c n"は更新されない。

countのメソッドを修正してみる

C := Object clone do (
 n := 1
 count := method(self n := n + 1)
 asString := n asString 
)

c := C clone

コマンドラインから使ってみる。

Io> doFile("C.io")
==> 1
Io> c
==> 1
Io> c count
==> 2
Io> c
==> 1
Io> c n
==> 2

内部のnはカウントアップされてるみたいだけど、表示が上手くいかない。

上記定義では、"self n"と指定することによって、self = cが持つスロットnにセットしましょうと明示すれば、"c n"がカウントアップされる。

こうすると、countが最初に呼ばれるまでは、"c n"によって、プロトである"C n"が参照されるが、countが呼ばれることによって、その処理ではcにnスロットを作成し、以降は"c n"によってcが持つnスロットが呼ばれることになる。

ここでちょっとイヤらしいのが、↓。

count := method(n = n + 1)

こう書いても動く。
このとき、左のnとしてself nを探し当てる。"="は"upadteSlot"だけど、自身に該当するスロットが無い場合でも、プロトオブジェクトのスロットを更新せずに、自身にそのスロットを作成して値を設定する。

asStringを修正してみる

C := Object clone do (
 n := 1
 count := method(self n := n + 1)
 asString := method(n asString)
)

c := C clone

コマンドラインから使ってみる。

Io> doFile("C.io")
==> 1
Io> c
==> 1
Io> c count
==> 2
Io> c
==> 2
Io> c n
==> 2

動いた!

asString := n asString

では、これが実行された時点でのn、つまり"1"がasStringとしてセットされるため、nが2,3,...と変わっても、asStringの内容は"1"のままとなる。そこで、

asString := method(n asString)

とすることによって、呼ばれた時点でのnを参照することができる。