From: Robert Gustavsson Date: 2001-02-26T09:40:03+09:00 Subject: [ruby-talk:11556] Re: Bottles of Beer finally in Ruby "Wayne Scott" wrote in message news:20010223143609K.wscott@ichips.intel.com... First I must say that this is no critique on your way of coding Ruby. I just used it as an excercise in re-factoring Ruby code (and learning/training Ruby in general). Anyone, feel free to comment and suggest improvements. Your version: --- class Fixnum def to_s "%d bottle#{self ==1 ? '' : 's'} of beer" % self end end c = 100 while c.nonzero? print "#{c} on the wall,\n" print "#{c},\n" print "Take one down, pass it around,\n" c -= 1 print "#{c} on the wall\n\n" end print "*burp*\n" --- My version #1: --- def b( num ) num.to_s + " bottle" + (num == 1 ? "" : "s") + " of beer" end 100.downto(1) { |c| puts "#{b(c)} on the wall," puts "#{b(c)}," puts "Take one down, pass it around," puts "#{b(c-1)} on the wall" puts "" } puts "*burp*" --- * I don't like the overriding of Fixnum just for formatting a special string (unique for this special app). Changed it to a method that returns the correct "N bottle[s] of beer" string. * "c = 100, while c -=1 ..." is IMO better expressed with 100.downto * Improved the readability by using puts instead of print. puts automatically appends "\n" but beware that puts x and print "#{x}\n" are only (almost?) identical when there's only one string. * Didn't like the % method call (because my Ruby knowledge on the % method is nearly nil) and I think my way of doing it is more readable and newbie-friendly. My version #2: --- def b( num ) num.to_s + " bottle" + (num == 1 ? "" : "s") + " of beer" end def beer( numberOfBeers ) numberOfBeers.downto(1) { |c| yield "#{b(c)} on the wall,\n#{b(c)},\nTake one down, pass it around,\n#{b(c-1)} on the wall\n" } end beer( 100 ) { |line| print line, "\n" } puts "*burp*" puts "*rap*" --- * But one cool thing I've picked up is iterators. I re-wrote it (and made it not so newbie-friendly) but using an iterator. Re-implemented the "\n" stuff. Now the beer method is a kind of generator. Pass in 50 to beer and it will count from 50 to 0. * Yes, I know that the yield is a bit (quite a big bit) unreadable. I just wanted to see how compact I could make it. Compactness is not always a good thing (ever?). Especially not when it comes to maintenance. * Made it a bit bilingual (it now also burps in Swedish) :-) /rob