"the" 演算子ライクな thing メソッドを Squeak Smalltalk で


「型を1つ引数にとり現在のスコープに唯一存在するその型のオブジェクトを返す演算子」である "the" ですが、あいにく Smalltalk のメッセージ式に the では馴染まないので thing というメソッドに置き換えて実装してみました。「クラス名 thing」でコールできます。

Smalltalk には thisContext という擬変数(代入できない変数)が予約語としてあって、実行時のコンテキスト(スタックフレーム)を文字通り「文脈」を表わすオブジェクトとして得て扱うことが可能なので、そこから手繰って指定された型(クラス)に属する唯一のインスタンスを特定できれば "the" 改め thing メソッドを比較的簡単に実装できます。

Behavior >> thing
   | env found |
   env := thisContext sender.
   found := (1 to: env size) select: [:idx | (env at: idx) isKindOf: self].
   ^found size = 1 ifTrue: [env at: found first] ifFalse: [self error: 'only one thing can be specified']


使い方はこうです。

たとえば

one
two
three
...

という foo.txt があったとして、その一行目を読み込む処理

| file |
file := FileStream fileNamed: 'foo.txt'.
file nextLine.
=> 'one'

を、このように書くことができます。

{  'foo.txt'.
   FileStream fileNamed: String thing.
   FileStream thing nextLine
} last
=> 'one'


後で参照するオブジェクトを生成するリテラルや式をGCされないように配列の要素にしておかないといけないのと、判定に #isKindOf: をつかっているのでサブクラスのインスタンスも拾ってきてしまう事の善し悪し等、いくつか問題もあるようなのでもう少し工夫が必要でしょうが、ネタとしてはとりあえずこんな感じで。