From: William Morgan Date: 2004-08-27T08:29:32+09:00 Subject: Re: python generators to ruby closures, help Excerpts (reformatted) from zuzu's mail of 26 Aug 2004 (EDT): > hence my interest in generators and streams in ruby. > > does that present a clearer contextual picture? Yes. I don't think you want the Generator class at all then. As the email you quoted said, Python generators are a solution to a problem that Ruby doesn't have. Generators have a place in Ruby but this ain't it. From what I can tell, all the functionality they build up in the Python example is just so that they can do thing that in Ruby can be done neatly with iterators, like this: odd = proc { |x| (x % 3) == 0 } div_by_3 = proc { |x| (x % 3) == 0 } result = (1 .. 10).reject(odd).reject(div_by_3).each { |x| print x } which has a "pipey" feel to it already, and with no preexisting work. If you really want all the syntactic sugar that they have, I would say something like this: class Pipe def initialize(&proc) @proc = proc end attr_reader :proc def +(other) Pipe.new { |x| self.proc[x] || other.proc[x] } end end module Enumerable def drain(pipe) self.reject { |x| pipe.proc[x] } end end Then you can do cool stuff like this: odd = Pipe.new { |x| (x % 2) == 0 } not_div_3 = Pipe.new { |x| (x % 3) == 0 } gt_5 = Pipe.new { |x| x <= 5 } p = odd + not_div_3 + gt_5 (1 .. 20).drain p # => [7, 11, 13, 17, 19] is_rb_file = Pipe.new { |s| s !~ /\.rb$/ } first_ten = proc do # here we have to use a closure i = 0 Pipe.new { (i += 1) > 10 } end.call Dir.entries(".").drain is_rb_file + first_ten # => the right thing ... which replicates the Python functionality, but without being quite so ugly. I personally find "positive pipes" a little easier than "negative pipes", but I've kept with their schemes for now. HTH. -- William