From: David Masover Date: 2010-08-22T18:07:24+09:00 Subject: Re: Adding *each* On Saturday, August 21, 2010 12:45:49 pm Ralph Shnelvar wrote: > In Ruby 1.8, what's the magic incantation so that I can do > > x = X.new > x.each {|y| puts y} You can do that anyway, it just doesn't do anything. All methods can accept a block, whether you want them to or not. All you have to do is yield to it. > I have read and reread Dave Thomas'*Programming Ruby 1.9* and ... well ... > I think I have to define *each* in class X and add some enumerable stuff First, why are you reading a 1.9 book and applying it to 1.8? Not that it should matter... You have to define 'each', yes, and you probably should include enumerable. I'll give a contrived solution to your contrived example: class X def each yield @x[0] yield @x[1] ... end end That 'yield' is a call to whatever block you passed. You could, of course, wrap it in a loop, or even an enumerator of its own: class X def each @x.each {|x| yield x} end end In this specific case, your contrived example is just contrived enough that we could take it a step further. You can grab that block as an actual argument by prefixing it with &, and apply it the same way. So, you can just pass it straight through, as Michael Fellinger suggested: class X def each(&block) @x.each(&block) end end It's contrived, but we may as well finish it up: class X # adds map, select, and so on include Enumerable def each(&block) # enum_for makes a new enum which uses 'each' by default return enum_for if block_given? @x.each(&block) end end I don't always include Enumerable, but I do always do enum_for, because not everything I want to enumerate is already in a form I can call 'each' on. For example: class Foo def all_bars return enum_for :all_bars unless block_given? yield :bar yield :foobar yield :baz end end Now I can do crazy stuff like: Foo.new.all_bars.map(&:to_s) Foo.new.all_bars{|b| puts b} That way, I can have multiple methods like that, each of which either behaves as the appropriate iterator, or gives me an appropriate enumerable (an enumerator, specifically) to play with. > I just don't get it. I hope I've helped, but if not, I'm going to need more than that. If you still don't get it, let me know what you don't get, and we can go from there.