Skip to content

Instantly share code, notes, and snippets.

@mattfield
Last active December 23, 2015 06:49
Show Gist options
  • Save mattfield/6596715 to your computer and use it in GitHub Desktop.
Save mattfield/6596715 to your computer and use it in GitHub Desktop.
Explanation of a splat function for linking purposes
// splat is an abstraction that wraps around _.map,
// turning a function into a mapping
// NB: we're using Underscore/Lodash here because we
// want our mapping to work everywhere. You could
// easily replace this implementation with one
// that uses the native Array#map
function splat(fn){
return function(list){
_.map(list, fn);
}
}
// Suppose we have a simple but overly-specific function
// that grabs a list of DOM elements, maps over them
// and returns their text contents
function getNavParams(){
_.map($('.nav-item'), function(element){
return $(element).text();
});
}
getNavParams();
//=> ["Home", "About", "Blog", "Shop"]
// This is very limited in scope and not very reusable.
// It could be better.
//
// What we're really interested in here is the body
// of the getElementParams function. Let's start
// by making it less element-specific
function getElementParams(el){
_.map($(el), function(element){
return $(element).text();
});
}
// Ok, so this is a bit better; it's no longer
// implementation-specific. However, we could
// abstract this further. Our mapping could be
// abstracted out into it's own function
// that takes an element and returns it's text
function getCurrentValue(el){
return $(el).text();
}
// Plugging that back in we get:
function getElementParams(el){
_.map($('.nav-item'), getCurrentValue);
}
// This is a big improvement and arguably much more
// readable. With useful function names we can see
// that we're mapping the getCurrentValue function
// over a list of DOM elements. This gives us the
// same result as before:
getElementParams();
//=> ["Home", "About", "Blog", "Shop"]
// But we can abstract this problem out even more.
// It's true that we may want to have a wrapper function
// that just grabs a list of values for a specific
// selector, and we certainly want to avoid having to
// rewrite our original get[something]Params function
// over and over with a different element each time.
// Let's use `splat` to create a single, reusable function
// that uses `getCurrentValue`:
var getParams = splat(getCurrentValue);
// Now what we have is a partially-applied mapping function
// that does the same thing as above. All it's waiting for
// is a list to operate on
var navParams = getParams($('.nav-item'));
navParams;
//=> ["Home", "About", "Blog", "Shop"]
var ingredients = getParams($('li.ingredient'));
ingredients;
//=> ["Milk", "Sugar", "Butter"]
// How about another use for `splat`. We'll use another small
// function, `get` that takes the name of a property and
// returns a function that gets that property from an object
function get(attr){
return funtion(object){
return object[attr];
}
}
var ingredients = {
"milk": "300ml",
"sugar": "200g",
"butter": "3tbsp"
};
get('milk')(ingredients);
//=> "300ml"
// Let's make our data structure a bit more high-level
// and make use of splat
var recipes = [
{ "milk": "300ml", "sugar": "200g", "butter": "3tbsp" },
{ "milk": "120ml", "sugar": "100g", "butter": "1tbsp" },
{ "milk": "1 pint", "sugar": "2 cups", "butter": "300g" }
];
splat(get('milk'))(recipes);
//=> ["300ml", "120ml", "1 pint"]
// That's way nicer than doing the same thing "longhand"
// like this:
//
// splat(function(recipe){ return recipe.milk })(recipes);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment