From: Tanaka Akira Date: 2009-07-30T01:49:35+09:00 Subject: [ruby-dev:38944] Re: Enumerator#peek In article , keiju@ishitsuka.com (石塚圭樹) writes: > ただ, ソート済みを前提としないで処理できるので, ソートされてない状態の > ものをわざわざソートしてコントロールブレーク処理するのと変わらないかも > 知れません. メソッドの仕様として、ソート済みかどうかで結果が変わらなくて わかりやすいのは良いですよね。 でも、メモリとのトレードオフで、メモリ消費に耐えられないこと もあるので用途によっては困ります。 Ruby では、ソート済みであることをプログラマが知っている状況 に対する支援はかなり手薄ですよね。たまに話にあがる bsearch とか。ソート済みの複数の並びをマージするなんてのもあっていい ような気がします。 (COBOL ではこれをマッチングというらしいのですが) >>狙っているところが違う感じでしょうか。 > > うーん. Enumeratorってかなり応用的なクラス(Enumerabbleから生成される) > なので, peekっていうのは, ちょっと違和感があるかも. あー、場合にもよるんですが、IO や Array に対する Enumerator がそのような意味で応用的であるというのは間違っていると考えて います。IO や Array などに対する外部イテレータを実現するのは 簡単なのに、Fiber を使うのは無駄が過ぎます。 たとえば、enum = io.lines としたときに enum.next は、結局 io.gets するだけなのに、Fiber が使われるのはなんとも無駄です。 もし、Enumerator.external_iterator { ... } というような形式 で enumerator が生成できて、next は指定したブロックを呼ぶだ け、というのが実現できれば、(私の構想では next は先読みの処 理もしますが) io.lines は Enumerator.external_iterator { io.gets or raise StopIteration } で実現できます。 IO, Array, Range 等、基本的なクラスの Enumerator は、ちょっ とがんばって効率の良い外部イテレータを提供して良いのではない かと思っています。 > ソートされているという前提でですね. ということは, slice_byさえあれば, > コントロールブレーク処理ではpeekは必ずしも要らないって言っていません? この例ではそうですね。peek が本当に有効なのはより複雑なケー スです。コントロールブレークでブレークキーが複数あるとか。 出した例が適切ではなかったかも知れません。 >>まぁ、values が大きくなるとメモリの点では悲しいケースが出て >>くるかも知れませんが。 > > たしかに, fairyでもgroup_byでvaluesを渡すのはどうかと言われています > (^^;; そういえば、[ruby-dev:38934] のコードで | a = %w[banana banana durian orange orange orange] | a.inject_by(proc{|w| w}){|key, sum, value| sum += value}.each{|key,sum| puts "#{key} #{sum}"} というのは、配列を作らないで済むという点を狙っていると思うの ですが、sum += value というところが意味不明です。ブロック変 数の sum に代入してどうすんだ、とか、value はどこから出てく るのか、とか。 思うに、複数のマシンに分散させて処理をやろうというなら、単語 数を数えるときの足し算のように associative な演算は、 associative であることを利用した仕掛けでやったほうがいいんじゃ ないかなぁ、と思います。associative であれば、つまり、 (a+b)+c=a+(b+c) のような関係の演算であれば、各マシン内で個々 に結果をまとめられますから。 inject だと、先頭から順にやっていかなければならない感じがし ます。つまり、associative でない演算を与えてよい、という感じ が。 > each_with_peekもEnumeratorのつもりなので外部イテレータにできると考えて > います. それにslice_byでもEnumeratorとして扱えば実現可能な気がしますが? each_with_peek を Enumerator にするというのは、きっと Fiber を使うことになりますよね。それは嫌です。あと、each_with_peek は最後の要素での先読みをどうするかが問題ですかね。nil とする と、nil という要素があったときと区別できません。 あと、slice_by は配列にしちゃいますから、メモリの点で嫌です。 > peekで出来ることが, slice_byの様なものですべて実現可能ではないかも知れ > ませんが, slice_byみたいなものの方が好みだなぁ. slice_by は slice_by でいいんじゃないでしょうか。 slice_by で簡単にできることは、slice_by でやるほうがいいと思 います。 peek は、より低級でより応用範囲が広いものが狙いです。 コントロールブレークでブレークキーが複数あるというのは、結構 一般的みたいです。情報処理技術者試験に出てくるほど。 読んだことはないので確かなわけじゃないですが、「二段のコント ロールブレイク処理」などと目次にある本もあるようです。 http://gihyo.jp/book/2002/4-7741-1607-6 peek は、そういうところを支援するベースになるものです。 そのまま使うというよりは部品なんですが、先読みが必要なのは (構文解析と考えると) かなり確かなので、まずそこをつけるのは どうか、という話です。 -- [田中 哲][たなか あきら][Tanaka Akira]