From: Gavin Kistner Date: 2005-04-22T23:11:52+09:00 Subject: Re: for .. in .. else? On Apr 22, 2005, at 7:34 AM, Adam Keys wrote: > Maybe I missed something, but when I extracted this code and ran it in > irb, it didn't work like I thought it would: It should have been 'if' instead of 'unless'. Or, make it reusable: class Array def each_or_empty( options = {} ) if self.empty? empty_block = options['when_empty'] || options[:when_empty] || options['empty'] || options[:empty] empty_block.call() if empty_block else each_block = options['each'] || options[:each] self.each{ |item| each_block.call( item ) } if each_block end self end end some_songs = %w| song1 song2 song3 | no_songs = [] [some_songs, no_songs].each_with_index do |collection, i| puts "Checking collection ##{i}" collection.each_or_empty :each => lambda{ |song| p song }, :when_empty=>lambda{ p 'no songs!' } end puts "...done" #=> Checking collection #0 #=> "song1" #=> "song2" #=> "song3" #=> Checking collection #1 #=> "no songs!" #=> ...done > > irb(main):087:0> songs > => ["Rocky Raccoon", "As My Guitar Gently Weeps", "She Came In Through > The Bathroom Window"] > irb(main):088:0> unless songs.each do |song| > irb(main):089:2* p song > irb(main):090:2> end.empty? > irb(main):091:1> p 'no songs!' > irb(main):092:1> end > "Rocky Raccoon" > "As My Guitar Gently Weeps" > "She Came In Through The Bathroom Window" > "no songs!" > => nil > irb(main):093:0> > > The presence of 'no songs!' is not what I'd expected. >> >> Yours is different from Hal's, because in Hal's the iteration through >> the song list is sort of a side-effect of the testing of the >> condition, whereas you're just doing a standard chaining thing. And >> you do create a temporary array :-) (the return value of #reject) > > This makes sense in isolation, however given the above result I'm > curious as to what is actually going on. As to the temporary > variable, I am more tired of having "foo = []" all over my code. > >> You could perhaps make it easier to read with a different formatting: >> >> ary.reject {|e| e.some_predicate? } .each do |f| >> f.do_something >> end >> >> or something. (Definitely lose the one-space indenting.) If your >> friend still has trouble with it, buy him the Pickaxe :-) > > I agree the {} block looks more like something that yields a value > than do..end. I think I had it that way at first but the line spilled > over past column 80 so I changed it to a do...end, which I use when a > block spans multiple lines. Is that a common idiom or am I unique in > this regard? > > -- > ~akk > http://therealadam.com > > > -- (-, /\ \/ / /\/