Functionalism w/ Underscore.js
Here we use the underscore.js javascript library to explore code changes from traditional, procedural solutions to functional chaining solutions.
by maxisam
HTML
<script src="http://www.gridlinked.info/cdn/js/underscore-min.js"></script>
<script src="http://www.gridlinked.info/cdn/highlighter/head.load.min.js"></script>
<script src="http://www.gridlinked.info/cdn/highlighter/head_highlighter.js"></script>
<link rel="stylesheet" href="http://www.gridlinked.info/cdn/css/jsFiddle_embed.css">
<body>
<div id="body">
<div id="header"></div>
<div id="contents">
<div id="intro">
<p>
Functional programming with <strong><a href="http://documentcloud.github.com/underscore/" target="_blank">Underscore.js</a></strong>.
</p>
</div>
<h2><code><span class='code'>Scenario</span></code></h2>
<br/>
<div class="contents">
<div class="bullet">
<div class="description">
Let's explore the migration from <span class="underline">traditional</span> to <span class="underline">functional</span>
approaches to implement a solution to an easy programmatic challenge. Consider the objective below:
<ul>
<li>Convert a list of names to instances of People objects</li>
<li>Ask each person to speak</li>
</ul>
<br/>
The code samples in this tutorial will all use a factory method <code><span class='code'>buildPerson()</span></code> to build a Person object:
<pre class="brush: js;">
function buildPerson(name, target) {
return {
speak: function(where) {
if ( !where ) where = target;
var words = 'Hello, my name is <span class="answer">{0}</span><br/>';
where.append( supplant(words, [name]) ); ...
JavaScript
(function(_, $) {
// http://skilldrick.co.uk/2011/07/easy-functional-programming-in-javascript-with-underscore-js-part-1/comment-page-1/#comment-9919
function logTitle(title, target) {
if (!target) { target = $("body"); }
var format = "<span class='title'><br/> {0}: <br/></span>";
target.append(supplant(format, [title]));
}
function logAnswer(answer, target) {
if (!target) { target = $("body"); }
var format = "Hello, my name is <span class='answer'>{0}</span><br/>";
target.append(supplant(format, [answer]));
}
// supplant() method from Crockfords `Remedial Javascript`
function supplant(template, values, pattern) {
pattern = pattern || /\{([^\{\}]*)\}/g;
return template.replace(pattern, function(a, b) {
var p = b.split('.'),
r = values;
try {
for (var s in p) {
r = r[p[s]];
};
} catch (e) {
r = a;
}
return (typeof r === 'string' || typeof r === 'number') ? r : a;
});
};
// Return Cat object with `speak` ability
function buildPerson(name) {
return {
speak: function(target) {
logAnswer(name, target);
}
};
}
// ****************************************************************
// Traditional Approach
$("#runSolution1").one("click", function() {
var names = ['Thomas Burleson', 'John Yanarella', 'Indiver Nagpal'];
var people = [];
for (var i = 0, len = names.length; i < len; i++) {
people.push(buildPerson(names[i]));
}
$("#outputSolution1").html("");
for (var i = 0, len = people.length; i < len; i++) {
people[i].speak($("#outputSolution1"));
}
$("#runSolution1").hide();
});
// Let's use underscore.js library API: map() and each()
//...