whileTrue: の罠
久しぶりに Smalltalk は全部メッセージなんだよ、#ifTrue:ifFalse: も構文じゃなくってTrue と False の ポリモーフィズムで実現されているんだよっ、と言う話を Smalltalk を知らない人にやりました。
実際に True >> ifTrue:ifFalse のコードを見せると、うわっ、なにこれと驚いてくれます。そのおどろきっぷりが快感。調子にのって BlockContext >> whileTrue: も見て見て、・・・とやって失敗しました。
BlockContext >> whileTrue: aBlock "Ordinarily compiled in-line, and therefore not overridable. This is in case the message is sent to other than a literal block. Evaluate the argument, aBlock, as long as the value of the receiver is true." ^ [self value] whileTrue: [aBlock value]
whileTrue: はリテラルブロックに送られる場合は インライン展開されるのですが、それ以外の場合(変数に束縛されていたり)は、このメソッド中のコードが実行され、改めて インライン展開されるわけです。その為のコードだから、このコードはどう読んでも期待通りに動かないわけで。
はぅぅ、Smalltalk スゴイぞな空気が一気に冷えたですよ。
この手のインライン展開されるものは、実際には実行されないけれど等価の Smalltalk コードがメソッド中に書いてあると思いこんでいたのが敗因です。しくしく。ちゃんとコード読んでいないから...。