Skip to content

Instantly share code, notes, and snippets.

@sbaldwin24
Created September 16, 2014 08:42
Show Gist options
  • Save sbaldwin24/48f71b085040fa54125f to your computer and use it in GitHub Desktop.
Save sbaldwin24/48f71b085040fa54125f to your computer and use it in GitHub Desktop.
99 Bottles of Beer with Underscore
This imperative version, while somewhat contrived, is emblematic of an imperative
programming style. That is, the implementation describes a “99 Bottles of Beer” pro‐
gram and exactly a “99 Bottles of Beer” program. Because imperative code operates at
such a precise level of detail, they are often one-shot implementations or at best, difficult
to reuse. Further, imperative languages are often restricted to a level of detail that is good
for their compilers rather than for their programmers (Sokolowski 1991).
By comparison, a more functional approach to this same problem might look as follows:
function lyricSegment(n) {
return _.chain([])
.push(n + " bottles of beer on the wall")
.push(n + " bottles of beer")
.push("Take one down, pass it around")
.tap(function(lyrics) {
if (n > 1)
lyrics.push((n - 1) + " bottles of beer on the wall.");
else
lyrics.push("No more bottles of beer on the wall!");
})
.value();
}
The lyricSegment function does very little on its own—in fact, it only generates the
lyrics for a single verse of the song for a given number:
lyricSegment(9);
//=> ["9 bottles of beer on the wall",
// "9 bottles of beer",
// "Take one down, pass it around",
// "8 bottles of beer on the wall."]
Functional programming is about pulling programs apart and reassembling them from
the same parts, abstracted behind function boundaries. Thinking in this way, you can
imagine that the lyricSegment function is the part of the “99 Bottles” program that
abstracts lyric generation. Therefore, the part of the program that abstracts the assembly
of the verse segments into a song is as follows:
// === 99 Bottle Program === //
function song(start, end, lyricGen) {
return _.reduce(_.range(start,end,-1),
function(acc,n) {
return acc.concat(lyricGen(n));
}, []);
// And using it is as simple as:
song(99, 0, lyricSegment);
//=> ["99 bottles of beer on the wall",
// ...
// "No more bottles of beer on the wall!"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment