retroforth/example/99-bottles.retro
crc 9e03717deb normalize names for examples (with a couple of exceptions), closes #38
FossilOrigin-Name: 088675e452ed86a712563c8b2597fe4d47da59bdea0e40becdd1e028a84c47b0
2021-01-24 01:13:04 +00:00

45 lines
1.2 KiB
Forth

# 99 Bottles
Display the text for the *99 Bottles of Beer* song.
For this, I'm using `s:evaluate` to construct words which
display a string when called. This lets the majority of the
code read nicely.
~~~
{ 'bottle 'bottles 'of 'beer 'on 'the 'wall 'no 'more
'Take 'one 'down, 'pass 'it 'around }
[ dup ':%s_'%s_s:put_sp_; s:format s:evaluate ] a:for-each
~~~
Handling of the exact text related to the number of bottles
is done with a simple array of functions that get selected
based on the number of bottles left. This is done with a
very simple filter, where the number of bottles for the
purpose of the text is in a set of 2 or more, 1, or none.
~~~
{ [ no more bottles ]
[ #1 n:put sp bottle ]
[ dup n:put sp bottles ]
} 'BOTTLES const
:number-bottles
dup #2 n:min BOTTLES swap a:fetch call ;
~~~
Thanks to the programatically generated words for the
verse text, the main code is nicely readable.
~~~
:display-verse
number-bottles of beer on the wall nl
number-bottles of beer nl
n:dec Take one down, pass it around nl
number-bottles of beer on the wall nl ;
:verses (n-)
repeat 0; nl display-verse again ;
#99 verses
~~~