2004-01-25 21:29:41 +0900 (1720d); rev 2
Ruby のイテレータを典型的なパターンに分類した。
典型的な実例は Array#each、Hash#each、String#each_byte など。
最もありがちなイテレータの使いかた。 コレクションオブジェクトの各要素について順番にアクセスしていくときに使う。
また、Array#each_index や Integer#upto のように、 必ずしも「要素」でないオブジェクトに対して繰り返すこともある。
[実装例]
class SomeCollection1
def each
list = @list
while list
yield list.value
list = list.next
end
end
end
class SomeCollection2
def each(&block)
@items.each(&block)
end
end
実例は IO#each、SMTP#sendmail など。
結果全部を一気に返すとでかすぎて危険な時に、 文字列 (など) を少しづつ渡すタイプ。 IO#each はどちらかというと行に分割するほうが主目的だが、 仕事を分割する目的にも (確実ではないが) 使えるので挙げてみた。 このタイプの特徴として、ブロックの引数を再現できないことが多い。
典型的な例は Enumerable#map, select, inject など。
オブジェクトをパラメータ化したい時は引数を渡す。一方、コードをパラメー タ化したい時はイテレータを使ってブロックを渡す。テンプレートメソッドと かストラテジーと呼ばれるものがこの範疇である。このタイプはブロックの 返り値に意味があることが多い。
典型的な例は IO#open、timeout など。
イテレータブロックの実行中だけ特定の環境を設定する。 必然的にこのタイプのイテレータは 「一回だけくりかえされるイテレータ」であることが多い。 開始と終了があるものにはほぼまちがいなくこのイテレータが適用できる。 特に終端が必須である場合は、ensure と組み合わせて 確実に終端が行われるイテレータを提供するとよい。
ちなみに C の malloc なんかは範囲型イテレータにできてもよさそうである。
[実装例]
class Resource
def Resource.open(rc_name)
begin
rc = new(rc_name)
yield rc
ensure
rc.free
end
end
end
典型的な例は module_eval と instance_eval。
インタプリタのコンテキストを設定するときに使う。 範囲型の特殊形。
典型的な例は signal、Gtk::Widget#signal_connect など。
いわゆるコールバックルーチンの登録をするときに使う。
[実装例]
class Listener
def on_some_event(&block)
@some_event_handler = block
end
end
Related Pages: RubyPages RubyAndOtherLanguages RubyCodingStyle
system revision 1.162