Twenty Ways to FizzBuzz

An exercise in Javascript

It is one of the most famous challenges in programming, a common question at interviews, a display of minimal programming competency. Yet, FizzBuzz is a challenge that most programmers apparently can't solve.

It is usually worded something like this:

Write a program that prints all the numbers from 1 to 100. For multiples of 3, instead of the number, print "Fizz", for multiples of 5 print "Buzz". For numbers which are multiples of both 3 and 5, print "FizzBuzz".

Writing about FizzBuzz seems oddly fitting for my first blog post: I'm interviewing myself for the position.

This article will be exploring how an initial solution might evolve much beyond what's usually expected of it. Along the way I'll try to showcase several techniques applicable in Javascript, both the good and bad parts - eventually maybe even hints of elegance, intertwined with complete dead-ends that should not be followed by any means, but might prove to be interesting proof-of-concept solutions regardless.

I'll try to explain the motivations behind most steps of transformation, trying to keep the discussion language-independent, but also pointing out some non-trivial workings of Javascript here and there. All in all, finding the balance between pacing and the details of explanations will be a big challenge for me, a thin line I'll surely veer from often, please bear with me.

Setup:

All the code samples in this post will assume the presence of a global print function, which I have defined as an alias for console.log:
var print = console.log.bind(console);
(Note that the bind is necessary, as console.log (rightfully, as a method of console) expects this to be bound to console. If you just saved a reference to the function under a different name, you would receive an illegal invocation error.)

I felt that using a name that is less environment-specific might make the code samples easier to read.

I have also redefined the global window.print (which brings up the print dialog in most browsers) for this very page, so you can paste the examples directly into the developer console, if you're into that sort of thing.

Naive solutions (#1-5)

For a start, let's see some run-of-the-mill solutions, what I assume the common answers are at those job interviews. If your time is too precious, and you've seen enough basic FizzBuzz implementations in your time, you might as well skip to the next chapter.

#1: Tongue-in-cheek

In true TDD fashion, if we need to output one particular string, we should do just that. YAGNI, KISS and all.

print('1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz,16,17,Fizz,19,Buzz,Fizz,...');

We don't even need to make it a function, since we were only asked to do this once. At this point, our interview is probably over.

Sadly, typing this takes definitely more time than some of the simplest solutions below.

#2: A loop!

Time to show off that we have a firm grasp on three of the most fundamental control structures in programming: functions, loops and if statements! (Adding these one by one could make for more individual solutions, but I'll try to leave room in the 20 for more interesting ones.)

function fizzBuzz(){
	for(var i=1;i<=100;i++){
		if(i%5 === 0 && i%3 === 0){
			print('FizzBuzz');
		} else if(i%3 === 0){
			print('Fizz');
		} else if(i%5 === 0){
			print('Buzz');
		} else {
			print(i);
		}
	}
}

This is probably the lowest form of some sort of acceptable solution (the part where that majority can't get, apparently), but it still has a lot of issues, mostly with repetition. The program structure reflects that we will end up with exactly one output per iteration, but it comes with a cost: we repeat the modulo tests several times, and one of our cases is just a combination of two others. This latter redundancy was already part of the original task description, but as a natural language usually operates with less strict semantics than a programming language, I'd consider it less of an issue there. Code architecture doesn't have to mimic the way the task was phrased, and diverging from it already shows a higher level of abstract thought in the interviewee.

#3: Drier, with a small issue

Let's try to fix the second problem above:

function fizzBuzz(){
	for(var i=1;i<=100;i++){
		if(i%3 === 0){
			print('Fizz');
		} 
		if(i%5 === 0){
			print('Buzz');
		} 
		if(i%3 !== 0 && i%5 !== 0) {
			print(i);
		}
	}
}

Getting rid of the else commands reflects that our options are not exclusive, a number can be divisible by 3 and 5 at the same time.

However, this introduces an unexpected problem: due to the way we defined our print operation (see at the top), every print command results in a new line, breaking Fizz and Buzz into separate lines at multiples of 15.

To get around this, we can keep track of the things we want to output in a variable. Thus, we also recover this neat abstract property we lost with our latest transformation: we print strictly once per iteration, so our loop only contains one print command. (I see hints of structural programming in this property.)

function fizzBuzz(){
	var output;
	for(var i=1;i<=100;i++){
		output = '';
		if(i%3 === 0){
			output+='Fizz';
		} 
		if(i%5 === 0){
			output+='Buzz';
		} 
		if(i%3 !== 0 && i%5 !== 0) {
			output+=i;
		}
		print(output);
	}
}

#4: Most DRY

Our latest change allows us to get rid of the repeated modulo checks: if after two checks the aggregated output is still the empty string, we can be sure that our number wasn't divisible with either 3 or 5, so we can replace the last if check as such:

function fizzBuzz(){
	var output;
	for(var i=1;i<=100;i++){
		output = '';
		if(i%3 === 0){
			output+='Fizz';
		} 
		if(i%5 === 0){
			output+='Buzz';
		} 
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

But this solution doesn't feel perfect. Although we did get rid of two unnecessary, and possibly expensive checks, the semantics of the code changed slightly, it became harder to read: it might not be entirely clear that the output === '' case corresponds exactly to the statement "it was not divisible by either 3 or 5". We have increased the coupling of the system by leaning on this connection, and now understanding the individual lines requires a more global understanding of the code.

It would be probably cleaner if we introduced two new variables to store the results of the modulo checks, and reusing those we could both make our code expressive, but not repeat the modulo operations:

function fizzBuzz(){
	var output, currentNumberDivisibleBy3, currentNumberDivisibleBy5;
	for(var i=1;i<=100;i++){
		output = '';
		currentNumberDivisibleBy3 = (i%3 === 0);
		currentNumberDivisibleBy5 = (i%5 === 0);
		if(currentNumberDivisibleBy3){
			output+='Fizz';
		} 
		if(currentNumberDivisibleBy5){
			output+='Buzz';
		} 
		if(!currentNumberDivisibleBy3 && !currentNumberDivisibleBy5) {
			output+=i;
		}
		print(output);
	}
}

In reality, modulo operations are not that expensive, and our FizzBuzz program won't have any performance criteria to meet - we fell into the familiar trap of premature optimization (who knew Donald Knuth would come up this often in a post about FizzBuzz?). This might already be a slight overkill for this task, but clearly, avoiding overkill is anything but the aim of this write-up.

#5: parameters everywhere

If we presented any of the previous solutions at an interview, chances are the interviewer tried to throw us off our game by rephrasing the question in ways that make our implementation fail ("What if I want 150 numbers instead of 100?" or "What if I want multiples of 7 and 8?"). And until now, after every question we would have had to rewrite substantial parts of the code.

A very natural next step is turning every number in the original problem description into a parameter for our function, and we end up with something like this:

function fizzBuzz(length, fizzNumber, buzzNumber){
	var output;
	for(var i=1;i<=length;i++){
		output = '';
		if(i%fizzNumber === 0){
			output+='Fizz';
		} 
		if(i%buzzNumber === 0){
			output+='Buzz';
		} 
		if(i%fizzNumber !== 0 && i%buzzNumber !== 0) {
			output+=i;
		}
		print(output);
	}
}

Now a fizzBuzz(100,3,5) invocation will yield the same output as our earlier solutions, but we don't have to sweat if the requirements change.

But turns out other interview rooms have started using our implementation as a reference in the meantime, and we just broke the public API for this immense user base - ie. calling fizzBuzz() now would produce no output whatsoever, not even error messages. By adding some default values to the beginning of our implementation, we're creating a backwards compatible solution:

var length = length || 100;
var fizzNumber = fizzNumber || 3;
var buzzNumber = buzzNumber || 5;

If you're not from a Javascript background, it might be interesting to note here how the OR operator returns the first truthy argument it encounters, and not a boolean as it would in some other languages. For the rest of this page, I leave the setting of default parameter values (which will only get more and more complicated) as an exercise for the reader.

Signs of Sophistication (#6-7)

#6: more generality (the shape of things to come)

So far our programs handled a fixed number of values at which to display their special values - printing fizz and buzz at multiples of 3 and 5. (Do note how a generalized description of our program is foreshadowing generalized solutions of the problem!) We can extend this functionality easily by requesting these special values as parameters too.

A solution which takes 3 parameters (called FizzBuzzBang) could look like this:

function fizzBuzzBang(length, fizzNumber, buzzNumber, bangNumber){
	var output;
	for(var i=1;i<=length;i++){
		output = '';
		if(i%fizzNumber === 0){
			output+='Fizz';
		} 
		if(i%buzzNumber === 0){
			output+='Buzz';
		}
		if(i%bangNumber === 0){
			output+='Bang';
		} 
		if(i%fizzNumber !== 0 && i%buzzNumber !== 0 && i%bangNumber !== 0) {
			output+=i;
		}
		print(output);
	}
}

Which could be invoked with any three numbers we please: fizzBuzzBang(100,3,5,4)

Adding a 4th, 5th marker with this method would be increasingly painstaking. We didn't make our method more generic, we just made it tailored for an other task. The necessary realization is that the thing we should be paremetrizing here is the number of inputs: we need a solution which can work with an arbitrary number of these markers.

With array parameters we can specify both the numbers at multiples of which we want to print special terms, and while we're at it, the special terms themselves (In case there's a debate that Fizz and Buzz should not be followed by Bang).

function fizzBuzz(length, numbers, terms){
	var output;
	if(numbers.length !== terms.length) {
		throw "illegal arguments!"
	}
	for(var i=1;i<=length;i++){
		output = '';
		for(var j=0;j<numbers.length;j++){
			if(i%numbers[j] === 0){
				output+=terms[j];
			}
		}
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

Now fizzBuzz(100,[3,4,5],['Fizz','Buzz','Bang']); should output the same as our previous solution. Remember, you can paste these code snippets directly into the developer console to see them running, I've set up the print function globally on this page.

#7: increased cohesion

In our previous solution, the thrown exception is a code smell, highlighting a problematic aspect of our function: there's implicit coupling between the semantics of the numbers and the terms arrays, but this is not reflected in the code besides the thrown exception when they mismatch. They need to be the same length, otherwise we can't make unambiguous sense of the instruction.

The cohesion of the code could be increased if these things could not be separated from each other - their relation would become explicit, and we wouldn't need to throw that error anymore. In some way, this sort of clear connection could be found in our code earlier too (around solution #5), when we named the first input param fizzNumber, signaling that it will correspond to the value where we print "Fizz". (If we were doing some sort of metaprogramming, we could harness this information too. We'll get back to that...)

By packaging the number and term entities into one object (called marker for a lack of a better word), we can create a function that's more straightforward to use, taking an array of markers as parameter:

function fizzBuzz(length, markers){
	var output;
	for(var i=1;i<=length;i++){
		output = '';
		var number;
		var term;
		for(var j=0;j<markers.length;j++){
			number = markers[j].number;
			term = markers[j].term;
			if(i%number === 0){
				output+=term;
			}
		}
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

We can recreate the original output with fizzBuzz(100,[{number: 3,term: 'Fizz'},{number: 5, term: 'Buzz'}])

Dead-end: Reflection (#8-9)

Javascript's dynamic nature allows a program to analyze its own structure. When you're referencing an object property by its name as a string (or whenever you use the bracket notation, in general), you're already invoking a sort of reflection. To go further, a javascript program can inspect and change its very own source code too, enabling a form of metaprogramming. I'm going to explore this path in this chapter.

Disclaimer: whenever you think this is the tool for your current job, think again. The ideas in this chapter are meant as interesting proof-of-concept fiddlings showing off the language's capabilities, rather than practices to be followed.

#8: Semantic Parameter Names

We mentioned earlier how having a parameter named fizzNumber describes a somewhat implicit connection between the value of this parameter and the output string "Fizz". When we want to replace Fizz with Foo, we have to both change the Fizz string to Foo, AND rename the parameter to fooNumber - this redundancy is surely a code smell! Using some reflection trickery, we can make this connection automatically maintained!

Note: the redundancy is indeed a code smell, the very same one for which Clean Code advocates you don't name your collection itemsArray but simply items: there's no need for the variable name to hint at implementation details, which might end up misleading soon. Of course, this is not the path we're taking now.

The basic idea is the following: a function can access its own source code, which enables it to see both the value and the name of the parameter it was passed. Let's see how:

function fizzBuzz(fizzNumber, buzzNumber, limit){
	//named f to not break the layout - it should be called something like ownSourceCode
	var f = fizzBuzz.toString();
	//extracting an array of the function's parameter names:
	var paramNames = f.slice( f.indexOf('(')+1, f.indexOf(')') ).split(',');
	//let's also trim them, so our solution doesn't depend on code formatting style
	paramNames = paramNames.map(function(name){return name.trim();});
	//at this point, paramNames is ['fizzNumber','buzzNumber','limit'];

	var firstMarker = {
		value: eval(paramNames[0]),
		displayString: paramNames[0].toLowerCase().replace('number','')
	};
	var secondMarker = {
		value: eval(paramNames[1]),
		displayString: paramNames[1].toLowerCase().replace('number','')
	};

	for(var i=1;i<=limit;i++){
		var output = '';
		if(i%firstMarker.value === 0){
			output += firstMarker.displayString;
		}
		if(i%secondMarker.value === 0){
			output += secondMarker.displayString;
		}
		if(output === '') {
			output += i;
		}
		print(output);
	}
}

If we want to play the FooBar game instead of FizzBuzz, we can just change the names of the parameters of this function too fooNumber and barNumber. Crazy, huh?

The usefulness of this is questionable: a user of this function cannot specify the desired behaviour, only the developer in control of the source code can. This, too, can be solved.

#9: A Function Modifying Itself

To get around the limitation posed a few lines above, we can easily imbue our previous function with methods that change the names of the parameters, enabling the user of the function to specify the behaviour.

Let's start with a separate function modifying our original function's code. We start off the same way, extracting an array of params we can modify, then we slice out the function body which we pass to the Function constructor:

fizzBuzz.setFirstMarker = function(markerString){
	var f = fizzBuzz.toString();
	var paramNames = f.slice( f.indexOf('(')+1, f.indexOf(')') ).split(',');
	paramNames = paramNames.map(function(name){return name.trim();});
	//replace the first parameter's name
	paramNames[0]=markerString+'Number';
	//slice out the function body from the string representation
	var functionBody = f.slice( f.indexOf('{')+1, f.length-1 );
	//create a new function with the modified param list and body
	fizzBuzz = Function(paramNames.join(','),functionBody);
}

Almost there - as it is, this method only works on the first invocation, as the redefined fizzBuzz function doesn't have this very method defined on it anymore.

To make it truly an object rewriting itself, with two extra lines we can save a reference to this function, and re-attach it to the newly constructed fizzBuzz:

fizzBuzz.setFirstMarker = function(markerString){
	var f = fizzBuzz.toString();
	var paramNames = f.slice( f.indexOf('(')+1, f.indexOf(')') ).split(',');
	paramNames = paramNames.map(function(name){return name.trim();});
	paramNames[0]=markerString+'Number';
	var functionBody = f.slice( f.indexOf('{')+1, f.length-1 );
	var self = fizzBuzz.setFirstMarker; //<-- line added
	fizzBuzz = Function(paramNames.join(','),functionBody);
	fizzBuzz.setFirstMarker = self; //<-- line added
}

Now we can set the string to be printed any number of times before running fizzbuzz: (some assembly required): fizzBuzz.setFirstMarker('Foo'); fizzBuzz(3,5,100);.

Alas, now we have a function named fizzBuzz outputting foo and buzz! Resolving this discrepancy based on this chapter is left as an exercise for the reader.

Enough about these shenanigans, soon we'll look at proper ways to dynamically construct our functions.

Functional Programming (#10-12)

#10: Functions as Parameters

By now, we've replaced a lot of the constants of the problem with parameters. Yet, some aspects of the code (such as the fact that the outcome is decided by modulo operations) remained untouchable, seemingly inherent to the problem - but this needn't be the case.

In Javascript, functions are first-class citizens, which means the generalization can be easily continued by specifying the operation that determines whether we print the number or some special string instead.

We can easily pass a function reference to this function:

function fizzBuzz(operation){
	var output;
	for(var i=1;i<=100;i++){
		output = '';
		if(operation(i,3) === 0){
			output+='Fizz';
		} 
		if(operation(i,5) === 0){
			output+='Buzz';
		} 
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

A small problem is that our original operation, modulo, is so fundamental that it has it's own operator, which we need to wrap in a function before we can use our newest solution:

function modulo(dividend, divisor){
	return dividend%divisor;
}

Now we can expect the usual output when calling fizzBuzz(modulo);

Of course, if we insist, we can create a solution which doesn't require wrapping % into a new function...

#11: Accepting Basic Operators

Disclaimer: this solution belongs to the same dead-end we explored before, and it carries the same caveats. Please don't do this.

Using the evil eval, we can pass any two-operand operators (such as %,+,-, or even logical operators like ||,&&) themselves as parameters, almost verbatim. Given the selected operator, we can construct a string which, when evaled, will output the desired result without the need to construct additional functions. (Did I mention yet you shouldn't do this?)

function fizzBuzz(operator){
	var output;
	for(var i=1;i<=100;i++){
		output = '';
		if(eval(i+operator+3) === 0){
			output+='Fizz';
		} 
		if(eval(i+operator+5) === 0){
			output+='Buzz';
		} 
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

You can call this construct simply like this: fizzBuzz('%');. We do need to wrap the operator in quotation marks to get a string, but it's not like this is the only problem with this approach...

#12: Predicates

A practical problem with the previous two solutions is the fact that the return values of the operations were still always compared to zero. This, for example, made using any sort of addition useless (staying with the set of natural numbers for now).

It seems like these check conditions should be parametrized too - but learning from our previous mistakes, it also seems clear that for high cohesion, these should not be separated from the operations themselves.

We should encompass the entire ruleset for determining whether a special value is printed in functions containing both the operation and the decision condition. These predicate functions returning boolean values will be a very useful first step in giving elegant functional solutions to our problem.

Writing our familiar modulo function with this in mind:

function modulo(dividend, divisor){
	return (dividend%divisor === 0);
}

enables us to simplify the main logic:

function fizzBuzz(predicate){
	var output;
	for(var i=1;i<=100;i++){
		output = '';
		if( predicate(i,3) ){
			output+='Fizz';
		} 
		if( predicate(i,5) ){
			output+='Buzz';
		} 
		if(output === '') {
			output+=i;
		}
		print(output);
	}
}

The benefits of this approach will be more apparent later.

Array methods (#13-15)

Before we delve into using array methods, it would be really neat if every collection in our problem domain was an array. For example, the number range our loop is iterating through can be trivially constructed as an array:

var range = [];
for(var i=1;i<=length;i++){
	range.push(i);
}

Using this array will enable us to formulate our solution in statements more closely resembling first-order logic.

Creating the array of numbers in a for loop is the most straightforward solution. If you tried using the Array constructor (new Array(100)), you'd find that calling array functions such as forEach or map on this array will run exactly 0 times, skipping the non-initialized key values. To get an array with a 100 initialized, albeit still undefined values, you can use ES6's new fill() method of the Array prototype:
new Array(100).fill(undefined); //currently Firefox only!

Interestingly enough, although every value is still undefined, array functions can be applied properly to this new array.

An ES5-compatible one-liner for the same task is the following:

Array.apply(null, {length: 100})

See a nice explanation of the workings of this "hack" here on stackoverflow. The very fact that this line of code requires a 2 page explanation should be enough reason not to ever use it in production code.

#13: Using forEach

The first array method we tackle is forEach.

It's mostly trivial to transform one of our early solutions (say, #5) into one using forEach:

function fizzBuzz(length, fizzNumber, buzzNumber){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	var output;
	range.forEach(function(i){
		output = '';
		if(i%fizzNumber === 0){
			output+='Fizz';
		} 
		if(i%buzzNumber === 0){
			output+='Buzz';
		} 
		if(i%fizzNumber !== 0 && i%buzzNumber !== 0) {
			output+=i;
		}
		print(output);
	});
}

Note that the callback in forEach also receives the current index as a second parameter. In case we use one of the above mentioned alternative methods to generate the range array, the current number might be represented not by the value but the index of the current element. In that case we can just replace the callback function's first line with function(_,i) (_ signaling an unused parameter in this case).

Regardless, this solution doesn't yet showcase much elegance we expect from a functional solution. We aimed at replacing every collection in our solutions with arrays, and earlier we already gave a solution representing the "fizz" and "buzz" markers and their conditions as collections themselves. Let's create a version of solution #7 using forEach:

function fizzBuzz(length, markers){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	var output;
	range.forEach(function(i){
		output = '';
		markers.forEach(function(marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
		});
		if(output === '') {
			output+=i;
		}
		print(output);
	});
}

#14: Using map

We can achieve a better separation of concerns than our last solution, printing inside our forEach is a sort of side effect which muddles the responsibilities of the sections of our code. Using Array.prototype.map(), we can use a separate statement to extract the values, and an entirely different statement to print the results.

function fizzBuzz(length, markers){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	var output;
	var outputs = range.map(function(i){
		output = '';
		markers.forEach(function(marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
		});
		if(output === '') {
			output+=i;
		}
		return output;
	});
	print( outputs.join('\n') );
}

Instead of using join() we can also make our print function accept an array argument, or use an additional array method to print every output string:

	outputs.forEach(function(output){
		print(output);
	});

The true benefit of this approach is that we've created a sort of processing pipeline, where every input and output is a collection of the same type (an array in this case), which allows very flexible composition.

For example we could add a filter (an array to array transformation) between any two operations, or chain the commands without creating variables just to store intermediate values:

function fizzBuzz(length, markers){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	var output, number, term;
	range.map(function(i){
		output = '';
		markers.forEach(function(marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
		});
		if(output === '') {
			output+=i;
		}
		return output;
	}).forEach(function(output){
		print(output);
	});
}

#15: Using reduce

Usually we can achieve the same result using any of the basic array methods, applying only slightly different transformations to our code. Picking the methods with the most appropriate semantics is a great service to our codebase. It increases both the readability, maintainability and composability of our code, we don't have to manually do the transformations that an other array method would include by default.

For example, when we want to create a single aggregate value representing an array (often at the end of a processing chain), the correct method to pick is reduce().

There's one part of our algorithm that naturally lends itself to this transformation: the construction of the output variable inside our forEach of the above solution, as at the end of the block, we end up with a single output value.

function fizzBuzz(length, markers){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	var output;
	range.map(function(i){
		output = markers.reduce(function(output,marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
			return output;
		},'');
		if(output === '') {
			output+=i;
		}
		return output;
	}).forEach(function(output){
		print(output);
	});
}

(We could also replace the map operation with a reduction to an other array, but the manual aggregation required to build this array would be just an other code smell that hints that map is the semantically correct method to use there - besides the fact that we want to create a 1-to-1 correspondence between the incoming and outgoing arrays.)

At this point, my only issue is that pesky last step of outputting the number if no matching marker was found, which is a stain of manual, imperative operation on this otherwise nice and functional solution. To solve this, we can just omit that part, then add an other mapping to the pipeline which replaces the empty strings with their indices: (actually, index+1 as it's 0-based)

function fizzBuzz(length, markers){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	//note the eliminated need for a top-level output variable;
	range.map(function(i){
		return markers.reduce(function(output,marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
			return output;
		},'');
	})
	.map(function(output, index){
		return output == ''? (index+1) : output;
	})
	.forEach(function(output){
		print(output);
	});
}

This is probably one of the nicer solutions you'll find in this article.

Constructing Functions (#16-17)

#16: Private Properties

Earlier we had some passing thoughts of making the function have some mutable properties describing its behaviour instead of taking parameters. Here we revisit the idea with the proper techniques, using a more object-oriented approach.

Just like in the last chapter, we'll be using the fact that functions are first-class citizens of the language: we can create functions which return other functions.

Functions can also be assigned properties like regular objects. This allows us to create a function object which is both callable and has methods on it - in our case, methods to manipulate the function's behaviour with the use of private properties.

Modifying some of our earlier solutions with this pattern is pretty straightforward, we just turn the parameters our original function requested into variables internal to the creator function: (I'm vary of using the word constructor)

function createFizzBuzz(){
  var fizzNum = 3;
  var buzzNum = 5;
  var length = 100;
  
  var fizzBuzz = function(){
    //... any of our solutions from above
  }
  
  fizzBuzz.setFizzNum = function(newVal){
	fizzNum = newVal; 
  }
  fizzBuzz.setBuzzNum = function(newVal){
	buzzNum = newVal; 
  }
  
  return fizzBuzz;
}

Now we can create a new instance of a fizzbuzz function with var fizzBuzz = createFizzBuzz(), and either call it without any parameters for the expected default output, or use the setFizzNum and setBuzzNum methods to change its behaviour.

The fizzNum and buzzNum variables are effectively private to this function (captured in closures for the created function and the setter methods), and we cannot get a reference to them from the outside.

Let's apply this approach to one uf our more complicated solutions from earlier, like the fully functional creation in #15. We can maintain a private array of markers, and provide methods for setting them - for simplicity's sake, I'll only give examples to a push and a get method:

function createFizzBuzz(){
  var markers = [{number: 3, term: 'Fizz'}, {number: 5, term: 'Buzz'}];
  var length = 100;
  
  var fizzBuzz = function(){
	var range = [];
	for(var i=1;i<=length;i++){ range.push(i); }
	range.map(function(i){
		return markers.reduce(function(output,marker){
			if(i%marker.number === 0){
				output+=marker.term;
			}
			return output;
		},'');
	})
	.map(function(output, index){
		return output == ''? (index+1) : output;
	})
	.forEach(function(output){
		print(output);
	});
  }
  
  fizzBuzz.getMarkers = function(){
	return markers;
  }
  
  fizzBuzz.addMarker = function(marker){
	markers.push(marker);
  }

  return fizzBuzz;
}

Now you can add a new marker after creating a fizzBuzz function, like this: fizzBuzz.addMarker({number: 4, term: 'Bang'}). There's a subtle issue with this solution, caught by the trained eye: we're returning a reference to a mutable private field, making it effectively not private!

This problem wasn't present in our previous solution, because our internal variables were primitive types, which a getter would have just copied, but an array is just passed by reference. This means that any modifications applied via the reference acquired this way will take effect on the fizzBuzz function operating on the same object. (Try: var markers = fizzBuzz.getMarkers(); markers.splice(0,2); fizzBuzz();)

To get around this, we can return a deep-copy of the private variable, breaking the link between the value returned and the internal array:

fizzBuzz.getMarkers = function(){
	return JSON.parse(JSON.stringify(markers));
}

(Hopefully you're using a library which provides nicer ways of deep copying an object, but the approach above is a surprisingly reliable and common way of doing this in vanilla js - at least until we have ubiquitous support for Object.assign().)

Immutability can be a very beneficial trait of a program (especially employing the functional approaches described above), but also the subject of an entirely different article. If the topic piques your interest, check out libraries adding immutability to Javascript such as Facebook's ImmutableJS, or the slightly more pragmatic seamless-immutable, or any of the numerous articles and discussions on the benefits of it.

#17: Using the Builder Pattern

Above we've created a function that behaves differently at different points in its life. Even using the same instance, we cannot be sure that invoking it twice with the same data will yield the same result. This is unusual, impractical and I'm not sure I'd like to work on any codebases employing such shenanigans.

Still, allowing the configuration of a function without modifying its source seems like a useful tool. Using the builder pattern we can split the life-cycle of this object into two: a configuration phase and a "runtime" phase where the behaviour of the function has been finalized. Ideally, we shouldn't even allow the main operation until the transition to this second stage is made explicit.

Of course, if the function is not callable until we've ended the configuration phase, it doesn't make much sense to deal with the same object between the two stages, nor to even keep returning a function at all in the configuration phase, a plain object will do.

Practically, we're just splitting the creation of a function into several optional steps (which also makes this a handy way of dealing with default values). Here's one way we could go about this:

var FizzBuzzBuilder = function() {
  var fizzNumber = 3;
  var buzzNumber = 5;
  var length = 100;
  
  var fizzBuzz = function(){
    //fizzBuzz logic capturing the private variables in a closure
  };
  
  this.setFizzNumber = function(number) {
      fizzNumber = number;
      return this;
  };
  this.setBuzzNumber = function(number) {
      buzzNumber = number; 
      return this;
  };
  this.finalize = function() {
    return fizzBuzz;
  };
};

To make the difference between private and public fields more clear, I've opted for a newable constructor function this time. Properties of this will be public to the outside world, and the public methods will access the private fields (such as the eventual fizzBuzz function itself) via closure.

We can use it like this:

var builder = new FizzBuzzBuilder();
var fizzBuzz = builder.setFizzNumber(2).setBuzzNumber(4).finalize();
fizzBuzz();

There's still a glaring problem with this solution - if we saved a reference to the builder object, we can still change the function's behaviour after calling finalize(), because the setter methods of the builder capture the same variables in their closures as the function does.

We can make the builder single-use for example by implementing some flag whether the function has been finalized yet, or we can even remove the setter properties upon finalizing. However, it would probably be better if we could use the finalize method to create new - truly finalized - function instances with the current configuration of the builder!

To do this, we can create an additional closure inside the finalize method, via an IIFE returning the fizzBuzz function, capturing the current values of the private fields at the time of finalizing.

I'll show an example to this method using a simpler fizzBuzz solution, using only primitive private values, which are easier to capture (if we used reference types, like the markers array, we would need to employ some copy mechanism).

var FizzBuzzBuilder = function() {
  var fizzNumber = 3;
  var buzzNumber = 5;
  var length = 100; 
    
  this.setFizzNumber = function(number) {
      fizzNumber = number;
      return this;
  };
  this.setBuzzNumber = function(number) {
      buzzNumber = number;
      return this;
  };
  this.setLength = function(number) {
      length = number; 
      return this;
  };
  this.finalize = function() {
    return (function(length,fizzNumber,buzzNumber){
		return function fizzBuzz(){
		var output;
		for(var i=1;i<=length;i++){
			output = '';
			if(i%fizzNumber === 0){
				output+='Fizz';
			} 
			if(i%buzzNumber === 0){
				output+='Buzz';
			} 
			if(i%fizzNumber !== 0 && i%buzzNumber !== 0) {
				output+=i;
			}
			print(output);
		}
	  }
	})(length,fizzNumber,buzzNumber);
  };
};

Using this solution, the behaviour of the finalized functions can't be changed anymore via the original builder, just try:

var builder = new FizzBuzzBuilder();
var f1 = builder.setLength(5).finalize();
var f2 = builder.setLength(10).finalize();
f1(); // -> will print 5 lines

Some might point out a small issue with the code above: for every instance of FizzBuzzBuilder, we're creating 4 new functions, even though it feels like this functionality could be shared by instances. A usual solution to this issue is putting the methods on the prototype, but in our weird use-case (i.e. extending a callable object with function properties), this is the price we have to pay for this functionality, as creating a callable object with a custom prototype is practically impossible. (And we sure don't want to put our fizzBuzz-specific methods on the global Function prototype!)

ECMAScript 6 (#18)

According to a March ruling by the ECMAScript Committee, no new article or blog post can be made on javascript without mentioning ECMAScript 6 (ECMAScript 2015) features.

In this section we try to shoehorn in some applicable features.

Note:

at the time of writing this post, most of the techniques described here are not yet supported by default in Chrome. To run this code sample, you should open this post in Firefox (don't forget that the samples here use the redefined `print` command, so you don't want to paste the snippets without either loading this page or manually reverting to console.log!), or use a polyfilled solution generated by BabelJS, which I will also include.

#18: Default parameters

After solution #5 I left the topic of default parameter values to the reader, but it's worth noting now how ECMAScript 6 introduces a handy feature for this purpose.

The new syntax calls for assigning the default values of params in the standard parameter list. These defaults will take effect when an undefined value is passed at the given position. Using default params, solution #5 would look like this:

function fizzBuzz(length=100, fizzNumber=3, buzzNumber=5){
	var output;
	for(var i=1;i<=length;i++){
		output = '';
		if(i%fizzNumber === 0){
			output+='Fizz';
		} 
		if(i%buzzNumber === 0){
			output+='Buzz';
		} 
		if(i%fizzNumber !== 0 && i%buzzNumber !== 0) {
			output+=i;
		}
		print(output);
	}
}

Sadly, Chrome does not support these features yet, but we can get a backwards-compatible version if we run this sample through Babel's online transpiling tool. The result is this:

'use strict';

function fizzBuzz() {
	var length = arguments.length <= 0 || arguments[0] === undefined ? 100 : arguments[0];
	var fizzNumber = arguments.length <= 1 || arguments[1] === undefined ? 3 : arguments[1];
	var buzzNumber = arguments.length <= 2 || arguments[2] === undefined ? 5 : arguments[2];

	var output;
	for (var i = 1; i <= length; i++) {
		output = '';
		if (i % fizzNumber === 0) {
			output += 'Fizz';
		}
		if (i % buzzNumber === 0) {
			output += 'Buzz';
		}
		if (i % fizzNumber !== 0 && i % buzzNumber !== 0) {
			output += i;
		}
		print(output);
	}
}

As you see, the conversion is pretty straightforward in this case. A difference to note compared to the naive solution I posted for the same task at the end of solution #5 is that

var param = paramValue || defaultValue;

will replace any falsy value (such as 0) with a default, while here we only want to replace truly undefined values.

Seeing that naive undefined check makes me doubt whether this code provided by Babel is truly equivalent to the default parameter syntax of the new standard.

Note that arguments[0] === undefined is susceptible to the old JS pitfall of overriding the value of undefined. I would be surprised if the ES6 implementations didn't cover this edge case with a more robust check, something along the lines of typeof arguments[0] === 'undefined'.

In fact, it turns out that Firefox 39's current default param implementation does differ in this behaviour from the code transpiled by Babel, you can easily check for yourself: adding var undefined=2; to our code will make the outputs different when we issue a command like fizzBuzz(100,2): FF correctly detects that 2 is not the special value undefined.

This is a silly edge-case, but I submitted a bug report of it to Babel regardless.

Pattern Matching (#19-20)

As a closing note, I'll backtrack a bit and try a fundamentally different approach: trying to rely on some recurring patterns of the problem, first hard-coded into the solution, then implementing a naive algorithm for recognizing these patterns in the general case.

I surely disappointed some readers with the title: alas, this chapter is not about pattern matching syntax in the language. Currently Javascript doesn't have much going on in that area, although ES6 does bring some basic destructuring - with hopefully full-fledged pattern matching somewhere along the ECMAScript roadmap.

#19: Programmer-Supplied Pattern

Even if we twist the challenge a bit, as long as we're dealing with modulo operations, the output will be strictly periodic. In the case of the original assignment, this period is 15 (because 3 and 5 are relative primes to each other).

That means we can determine the output for an arbitrary index just by knowing the index's position within the period - it's not entirely accidental that this leads us back to modulo operations again.

Let's create an array of transformations representing this period, where each item corresponds to the transformation that we have to apply at the current index. The index of the needed transformation will be easily determined by taking numberIndex%periodLength, leaving us with a transformation array like this:

var transformations = [
	fizzBuzzify, //0 - corresponds to 15
	identity,    //1
	identity,    //2
	fizzify,     //3
	identity,    //4
	buzzify,     //5
	fizzify,     //...
	identity,
	identity,
	fizzify,
	buzzify,
	identity,
	fizzify,
	identity,
	identity
];

Where the elements are references to the following basic functions:

var identity = function(n){
	return n;
}
var fizzify = function(n){
	return 'Fizz';
}
var buzzify = function(n){
	return 'Buzz';
}
var fizzBuzzify = function(n){
	return 'FizzBuzz';
}

Given this structure, the printing logic is reduced to a single line:

for(var i=1;i<=100;i++){
	print( transformations[i%transformations.length](i) );
}

While the brevity and declarative nature of this final line is neat, this solution feels a bit brutish - after all, we had to manually find out and type up the pattern, which obviously limits the usefulness of our program.

It would be a much nicer challenge to automatically extract these patterns from a sample - of course, this will require a very different input. Up next.

#20: Recognizing Patterns

I will create a function which is able to parse an existing FizzBuzz list (which can be the output of any of our previous solutions), recognize the rules governing it, and be able to extend it indefinitely.

This does not sound like a usability dream, but maybe in some cases, it is actually easier to type out the first few outputs of the desired pattern, and let the function figure out the periodicity. As a final test case, I'd like to invoke the function as such:

fizzBuzz([1,2,'Fizz',4,'Buzz'],100);

and receive the same 100-length output as any of our previous solutions.

Finding which numbers were replaced by special values in the sequence is trivial. For brevity's sake, let us now assume that the special output strings will always follow a PascalCase naming convention, which makes it easier to extract all the different strings used:

  var markers = {};
  sampleOutputs.forEach(function(element, i){
    if(isNaN( Number(element) )){
      var parts = element.split(/(?=[A-Z])/);
      console.log('parts:',parts);
      parts.forEach(function(part){
        if(!markers[part]){
          markers[part] = [];
        }
        markers[part].push(i+1);
      });
    }
  });

This gives us an object where the keys are the possible output strings, and the values are the arrays of numbers where the rule associated with the output matched. In the simplistic example above this yields {Fizz: [3], Buzz: [5]}

If we assume the output is generated by rules involving a single modulo operation only, and we list numbers from 1, the task is pretty simple given this data structure: the first number of every array is the number by which the modulo check was carried out.

However, I would prefer to create a more generalized solution, which can eventually be extended easily to support arbitrary intervals and rules besides modulo operations.

What I have in mind is a sort of a brute-force solution: generating predicate functions, running them against the list of numbers equal in length to the sample input, and checking whether the resulting array of "hits" corresponds to any of the above extracted arrays. Hopefully this will also enable us to employ some functional concepts along the way. (I'm not concerned about performance for now.)

For a start, I'll transform this object above to an array, in order to be able to use some nice functional composition later on:

for(key in markers){
	if(markers.hasOwnProperty(key)){
		markersArray.push({
			marker: key,
			matchingElements: markers[key]
		});
	}
}

Then I define a simple function for generating the modulo predicates:

function getPredicate(divisor){
    return function(element){
        return !(element%divisor);
    }
}

Using this function, we can create a simple algorithm for generating the outcomes for each predicate:

function generatePossiblePatterns(length){
	var generatedPatterns = [];
	for(var i=1;i<=length;i++){
		var predicate = getPredicate(i);
		var interval = [];
		for(var j=1;j<=length;j++){interval.push(j);}
		var outcome = interval.filter(function(element){
			 return predicate(element);
		});
		generatedPatterns.push(outcome);
    }
	return generatedPatterns;
}

This system can be easily generalized past modulo operations: we can add any predicate function returning a boolean which will be used to filter the array of possible elements. However, for simplicity's sake I'll finish this solution relying on some assumptions about modulo-based predicates.

At this point, all we have left is finding the matches between the extracted and the generated patterns. Disregarding error handling and complicated cases for now (i.e. assuming that some combination of our modulo predicates will match the provided pattern, and that every pattern will match only one predicate's output), we can do this with the following expression:

extractedPatterns.map(function(ePattern){
	return {
		marker: ePattern.marker,
		number: generatedPatterns.filter(function(gPattern){
			return ePattern.matchingElements.every(function(element, index){
				return gPattern[index] === element;
			});
		})[0][0]
	}
});

This will yield an array of objects that describe the rules governing our fizzBuzz pattern, in this case [{marker: 'Fizz', number: 3},{marker: 'Buzz', number: 5}].

Incidentally, this is the input format we used for some of our previous solutions, so we can use any of them to print the extrapolated FizzBuzz pattern. You can find this solution assembled into a self-contained gist here.

Calling the assembled function like this extrapolateFizzBuzz([1,2,'Fizz',4,'Buzz'], 100); outputs the full fizzBuzz sequence, which fulfills our initial test case, and concludes the 20th solution and this article.

Jump back to top or take the elevator.