From: Akinori MUSHA Date: 2009-05-10T02:23:41+09:00 Subject: [ruby-dev:38399] Re: Enumerable#gather_each --pgp-sign-Multipart_Sun_May_10_02:24:03_2009-1 Content-Type: text/plain; charset=ISO-2022-JP At Sat, 9 May 2009 15:30:20 +0900, Tanaka Akira wrote: > というわけで、Enumerable#gather_each(arg) {|ary| ... } の提 > 案です。引数には Proc を与えて、これは各要素について呼ばれ、 > 結果として分類結果を返します。gather_each はその分類結果が等 > しい連続した要素を配列としてまとめて yield します。 > > なお、分類結果が nil というのは特別扱いで、その要素は単独で > まとまりとなることを示します。  少し仕様がわかりにくいように思います。繰り返しというストリームの バッファという発想から、次のようなインターフェースを考案しました。 どうでしょうか。 class Enumerator class Buffer # status: 自由なメモ用途に提供 attr_accessor :status def initialize(yielder) @buffer = [] @yielder = yielder @status = nil end # バッファに追加 def push(item) @buffer.push(item) end alias << push # バッファの最後の要素を取り出す def pop @buffer.pop end # バッファをクリア def clear @buffer.clear self end # バッファが空かどうか def empty? @buffer.empty? end # バッファに溜まった要素数 def size @buffer.size end # バッファの内容を yield してクリア def flush @yielder.yield(@buffer) @buffer = [] nil end end end module Enumerable def buffer(&block) Enumerator.new { |yielder| buffer = Enumerator::Buffer.new(yielder) each { |*args| case args.size when 0 block.call(buffer) when 1 block.call(args.first, buffer) else block.call(args, buffer) end } buffer.flush unless buffer.empty? # ※終了時に自動flush } end end # 使用例: # 要素をバッファに溜めていき、 nil が現れたら # そこまでのまとまりを yield する p [1,2,3,nil,4,5,nil,6].buffer {|e, b| if e.nil? b.flush else b << e end }.to_a # 表示結果: [[1, 2, 3], [4, 5], [6]] > なお、複数行をまとめる方法として使いそうなものは、まとめる先 > 頭要素を検出する方法を指定するとか、他にもいくつかあるように > 思います。たとえば ChangeLog や mbox を扱うのには、先頭要素 > を指定するのがいいでしょう。そういうものはまた別のメソッドと > して作るのがいいのではないかと思います。  上記のインターフェースだと使用例のように区切りを渡さないことも できますし、 yield を追加の前にするか後にするかも自由です。また、 status/status= を提供することで状態遷移を扱うことも支援できます。  あとは、終了時のハンドラを定義すると上記の※印の代わりに実行 するようにするといいかなと思っています。 -- Akinori MUSHA / http://akinori.org/ --pgp-sign-Multipart_Sun_May_10_02:24:03_2009-1 Content-Type: application/pgp-signature Content-Transfer-Encoding: 7bit -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEABECAAYFAkoFvDMACgkQkgvvx5/Z4e5jnACfdGsZg1ZxXWQh8/4NhHNgmsKQ 7aYAoMBodU5ahO5Jf9+fVCf5p3nF34Ub =wDov -----END PGP SIGNATURE----- --pgp-sign-Multipart_Sun_May_10_02:24:03_2009-1--