In the previous article in this series, I put out a call for alternate implementations of the “watcher”-based FizzBuzz solution. Frank Quednau answered the call with this elegant bit of JavaScript:
const wordWatcher = (interval, word) => { let count = 0; return () => { count++; if (count === interval) { count = 0; return word; } return ""; } } const fizzWatcher = wordWatcher(3, "Fizz"); const buzzWatcher = wordWatcher(5, "Buzz"); for (number of Array(100).keys()) { const potentialFizzBuzz = `${fizzWatcher()}${buzzWatcher()}`; console.log(potentialFizzBuzz ? potentialFizzBuzz : number + 1); };
Let’s take a closer look at the code for the watcher, which is assigned a word and keeps track of when to say it:
const wordWatcher = (interval, word) => { let count = 0; return () => { count++; if (count === interval) { count = 0; return word; } return ""; } }
wordWatcher
has two parameters:interval
: The x in “Every xth number”word
: The word to be output
- It uses those parameters to customize the function that it returns: a function that when called, does two things:
- It increments its internal counter
count
, and - returns either
word
(if it’s time to say the word) or an empty string.
- It increments its internal counter
If you find yourself writing a lot of similar code with only minor differences — or worse, cutting and pasting code, followed by typing in those minor differences — you may be looking at an opportunity to use a function like this.
If you prefer to have your functions marked with the keyword function
, you can change out the arrow notation and the code will still work:
function wordWatcher(interval, word) { let count = 0; return function() { count++; if (count === interval) { count = 0; return word; } return ""; } }
With wordWatcher
defined, creating watchers for Fizz and Buzz is easy:
const fizzWatcher = wordWatcher(3, "Fizz"); const buzzWatcher = wordWatcher(5, "Buzz");
And here’s the loop that provides the output:
for (number of Array(100).keys()) { const potentialFizzBuzz = `${fizzWatcher()}${buzzWatcher()}`; console.log(potentialFizzBuzz ? potentialFizzBuzz : number + 1); };
- If it’s time to say Fizz, Buzz, or FizzBuzz,
potentialFizzBuzz
will contain that string. The calls tofizzWatcher()
andbuzzWatcher()
will also increment their internal counters. - If
potentialFizzBuzz
contains anything, its contents will be printed to the console; otherwise, the current number — which has 1 added to it because array indexes start at 0 and the FizzBuzz game starts at 1 — is printed instead.
You should check out the rest of Frank’s Gist, Fizzbuzzes in many colours, which looks at FizzBuzz solutions written in several languages.
What does it mean for code to be “elegant”, anyway?
In ordinary everyday use, elegant means “pleasingly graceful and stylish in appearance or manner.” The term has been adapted by people in problem-solving fields — science, mathematics, and yes, programming — to mean “pleasingly ingenious and simple”.
And that’s what elegant code is: pleasingly ingenious and simple. This FizzBuzz implementation is elegant because it solves the problem in just over a dozen lines, is simple and concise, and even provides some new insight into programming (the use of custom-generated functions to avoid repetition).
Here’s a good list of qualities of elegant code, courtesy of Christopher Diggins article, What is the Definition of Elegant Code?:
- It is succinct
- It is easy to understand
- Each function does one well-defined task
- It conveys the programmer’s intent
- It reflects the problem domain
- It is easy to modify and reuse
- If it fails, it is easy to identify that it is has failed, where it has failed, and why it has failed.
- Its behavior (in good and bad conditions) is easy to predict
Check out the following articles — sooner or later, you’ll be interviewed by a programmer who’ll want to know if you’ve given some thought to some of programming’s more philosophical questions, and “What does it mean for code to be elegant?” is one of them:
- Quora, via Forbes: What Does One Mean By ‘Elegant’ Code?
- Communications of the ACM: What Makes a Program Elegant?
- Word Aligned: Elegance and Efficiency
- The New Stack: This Week in Programming: On Writing Elegant Code
What’s next
FizzBuzzBazz! (or: Making FizzBuzz harder).
Previously, in the “Programmer interview challenge” series
- Programmer interview challenge 1: Anagram
- Programmer interview challenge 1, revisited: Revising “Anagram” in Python and implementing it in JavaScript
- Programmer interview challenge 1, revisited again: “Anagram” in Swift, the easy and hardcore way
- Programmer interview challenge 1, revisited once more: “Anagram” in Ruby and C#
- Programmer interview challenge 2: The dreaded FizzBuzz, in Python
- Programmer interview challenge 2, part 2: Functional FizzBuzz
- Programmer interview challenge 2, part 3: FizzBuzz, minus the modulo operator, plus grit
- Programmer interview challenge 2, part 4: Using “watchers” to play FizzBuzz “properly”