Language Ruby
(Using continuations, singleton classes)
| Date: | 09/15/06 |
| Author: | Victor Borja |
| URL: | n/a |
| Comments: | 8 |
| Info: | http://www.ruby-lang.org |
| Score: |
# 99 Bottles of beer, in Ruby
# By Victor Borja, Sep 14, 2006
# This one shows my favorite Ruby features:
# continuations, open classes, singleton classes, blocks and being funny!
class Integer # The bottles
def drink; self - 1; end
end
class << song = nil
attr_accessor :wall
def bottles
(@bottles.zero? ? "no more" : @bottles).to_s <<
" bottle" << ("s" unless @bottles == 1).to_s
end
def of(bottles)
@bottles = bottles
(class << self; self; end).module_eval do
define_method(:buy) { bottles }
end
self
end
def sing(&step)
puts "#{bottles.capitalize} of beer on the wall, #{bottles} of beer."
if @bottles.zero?
print "Go to the store buy some more, "
step = method :buy
else
print "Take one down and pass it around, "
end
@bottles = step[@bottles]
puts "#{bottles} of beer on the wall."
puts "" or wall.call unless step.kind_of? Method
end
end
callcc { |song.wall| song.of(99) }.sing { |beer| beer.drink }
Download Source | Write Comment
Alternative Versions
| Version | Author | Date | Comments | Rate |
|---|---|---|---|---|
| Readably re-opening Integer, teetotaller | Eric Budd | 01/06/08 | 0 | |
| In words | Daniel Straight | 07/10/06 | 1 | |
| object-oriented version | Mike Gertz | 04/20/05 | 3 | |
| shows inheritance, iterators, yield, etc | Kian Wright | 06/10/05 | 0 | |
| alternative version | Greg T. | 05/18/05 | 11 | |
| minimal version | Anonymous | 05/18/05 | 3 | |
| wall-based OO version | Kevin Baird | 07/07/05 | 2 | |
| monkeypatch and anonymous procs | J. B. Rainsberger | 04/04/07 | 0 |
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
Especialy the parts "wall.call" if you need the next bottle, "step = method :buy" if you have no beer left and "beer.drink" as what to do in each stanza.
I would actualy call it a geek poem.
For those of you who don't code Ruby: Learn Ruby, so you can enjoy reading this poem and writing your next scripts/applications/whatever.
The part I liked the more was the last line, especially "}.sing {", that makes use of a not commonly known behavior of ruby continuations. When the continuation is called the first time, the #sing message is sent to the value resulting from the body of callcc, however subsequent calls to the continuation (by means of wall.call) always send the #sing message to the nil object. I proved this by changing "song = nil" to "song = Object.new", now I understand why Victor used nil as the song, a very cleaver choice !.
I actually think I'll submit it.
(1..99).to_a.reverse.each do |bottle|
if bottle > 1
puts "#{bottle} bottles of beer on the wall, #{bottle} bottles of beer."
suffix = bottle > 2 ? "#{bottle -1} bottles of beer on the wall" : "1 bottle of beer on the wall"
elsif bottle == 1
puts "1 bottle of beer on the wall, 1 bottle of beer."
suffix = "no more beer on the wall!"
end
puts "Take one down, pass it around #{suffix}"
puts "--"
end
Nice codes.
num_bot = proc { |n| "#{n} bottle#{n == 1 ? '' : 's'}" }
99.downto(2) do |num|
puts "#{num_bot[num]} of beer on the wall, #{num_bot[num]} of beer!"
puts "Take one down, pass it around, #{num_bot[num-1]} of beer on the wall!"
end
puts "#{num_bot[1]} of beer on the wall, #{num_bot[1]} of beer!"
puts "Take one down, pass it around, no more bottles of beer on the wall!"