library: beer module: beer author: Peter Hinely version: 1.0, 1998 synopsis: Dylan version of 99 Bottles of Beer Inpsired by Jim Studt's version at http://www.ionet.net/~timtroyr/funhouse/beer.html disclaimer: This program does not advocate the excessive use of alcohol (or the use of static programming languages). define library beer use dylan; use format-out; end; define module beer use dylan; use extensions; use format-out; end; //////////////////////////////////////////////////////////////////////////// define constant *number-table* = begin let table = make(); local method insert-entries (number-strings, #key start = 0, increment = 1); for(number-string in number-strings, number from start by increment) table[number] := number-string; end for; end method; insert-entries( #("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen") ); insert-entries( #("twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"), start: 20, increment: 10 ); table; end; //////////////////////////////////////////////////////////////////////////// define method main (argv0, #rest ignore) format-out(" Dylan Bottles of Beer\n\n"); for (i from 99 to 0 by -1) format-out("%s of beer on the wall, %s of beer;\n", as-sentence-case(enumerate(i)), enumerate(i)); case i > 0 => format-out("Take %s down, pass it around, %s of beer on the wall.\n\n", pronoun(i), enumerate(i - 1)); otherwise => format-out("Go to the store, buy some more, ninety-nine bottles of beer on the wall.\n\n"); end case; end for; end method; //////////////////////////////////////////////////////////////////////////// define method enumerate (count == 0) "no more bottles" end method; define method enumerate (count == 1) "one bottle" end method; define method enumerate (count :: ) concatenate(as(, count), " bottles"); end method; //////////////////////////////////////////////////////////////////////////// define method as (type == , key :: limited(, min: 0, max: 99)) => number-string :: ; let the-element = element(*number-table*, key, default: #f); if(the-element) the-element; else let (tens-digit, ones-digit) = truncate/(key, 10); concatenate(*number-table*[tens-digit * 10], "-", *number-table*[ones-digit]); end if; end method; //////////////////////////////////////////////////////////////////////////// define method as-sentence-case (original :: ) let new-string = copy-sequence(original); new-string[0] := as-uppercase(new-string[0]); new-string; end method; //////////////////////////////////////////////////////////////////////////// define method pronoun (count == 1) "it" end method; define method pronoun (count :: ) "one" end method;