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 コードがメソッド中に書いてあると思いこんでいたのが敗因です。しくしく。ちゃんとコード読んでいないから...。