USING: kernel math math.ranges io sequences math.parser make arrays combinators unicode.case ; IN: bottles PREDICATE: no < integer 0 <= ; PREDICATE: one < integer 1 = ; PREDICATE: some < integer 1 > ; GENERIC: bottle ( n -- s ) M: no bottle drop "No more bottles" ; M: one bottle drop "One bottle" ; M: some bottle [ # " bottles" % ] "" make ; : bob ( n -- s ) [ bottle % " of beer" % ] "" make ; : bobw ( n -- s ) [ bob % " on the wall.\n" % ] "" make ; : list-bottles ( n -- s ) [ bobw >lower ] [ bob ] bi [ % ", " % % ] "" make ; : take-one ( n -- s ) dup 1 < [ drop 99 "Go to the store and buy some more, " ] [ 1- "Take one down, pass it around, " ] if swap bobw >lower 2array concat ; : verse ( n -- s ) [ list-bottles ] [ take-one ] bi 2array concat ; : song ( n -- ) 0 [a,b] [ verse print ] each ;