A from-scratch version of the Bottle Song in Lisp: bottle-song.lisp. We can see some nice features of FORMAT in action (conditionals, relative & absolute go-to, user extensions, pluralization, radix control, case conversion, etc.), but by far not everything that is offered.
;; * clisp bottle-song.lisp
(in-package :cl-user)
(defun bottle-song (&optional (in-stock 99) (stream *standard-output*))
;; Original idea by Geoff Summerhayes <sumrnot@hotmail.com>
;; Formatting idea by Fred Gilham <gilham@snapdragon.csl.sri.com>
;; Actual formatting & minor recoding by Kent M Pitman
;; <pitman@world.std.com>
;; Redone for conformance to <http://www.99-bottles-of-beer.net/>
;; by Michael Weber <michaelw@foldr.org>.
(format
stream
"~v{~1&~0%~
~000000%~
~000000%~
~000000%~
~00000000%~
~:/bottles/ ~
of beer on ~000%~
the wall, ~001:*~
~99/bottles/ of ~
beer.~1:*~%~[Go ~
to the store and~
~000@* buy some ~
more, ~/bottles/~
~00% of beer on ~
the wall.~01%~:;~
Take one down an~
d pass it around~
, ~999/bottles/ ~
~:*of beer on th~
e wall.~002%~]~}"
(1+ in-stock)
(loop for bottle from in-stock downto 0 collect bottle)))
(defun bottles (stream arg &optional colonp atp &rest args)
(declare (ignore atp args))
(format stream "~[~:[n~;N~]o more bottles~:;~:*~A bottle~:*~P~]"
arg colonp))
(bottle-song)
Alternatively, numbers can be printed as (properly capitalized) words with:
(defun bottles (stream arg &optional colonp atp &rest args)
(declare (ignore atp args))
(format stream "~[~:[n~;N~]o more bottles~:;~
~:[~2:*~R~;~2:*~@(~R~)~] bottle~:*~P~]"
arg colonp))
Ninety-nine bottles of beer on the wall, ninety-nine bottles of beer.
Take one down and pass it around, ninety-eight bottles of beer on the wall.Ninety-eight bottles of beer on the wall, ninety-eight bottles of beer.
[…]
Take one down and pass it around, ninety-seven bottles of beer on the wall.
UPDATE 2009-04-08: Fame, at last!
Zach Beane showed the bottle song sources (in form of a Format Automotivator) during his ILC2009 lightning talk about the Wigflig imperium!
