Skip to content

FrancisMurillo/the-power-of-functions-in-javascript

Repository files navigation

The Power Of Functions In JavaScript

The Power Of Functions In JavaScript

By Francis Murillo

On Apr. 14, 2016

At Manila, JavaScript #06

francisavmurillo@gmail.com

https://github.com/FrancisMurillo/the-power-of-functions-in-javascript

If It Is After April. 14

This is the original source of the presentation, the revised cut I used for the presentation is the presentation-shortened.org.

I had hoped to be able to give this in 30 minutes but I failed to realize that I think faster than I talk, showed too much code and tried to discuss a wide range. A valiant effort.

I hope this presentation will help you write good code and with a different lens. Thanks.

Foolish Assumptions

  • You know the basics of JavaScript syntax
  • I am talking about JavaScript in the browser
  • You and I hate presentations that waste time

A Little Background

Just a mediocre software developer.

Before We Begin

Judge a man by his questions rather than his answers

– Voltaire

Who here thinks JavaScript (in the browser) sucks?

JavaScript Sucks

Where do I begin?

  • Lousy type system
  • No module system
  • Global by default
  • No block scope
  • Monkey patching
  • The rest couldn’t fit on one slide

But I am not here to bash on the language.

How do we write good code in a (sucky but awesome) language?

Writing Good Code For JavaScript

How do write code that is…

  • Modular
  • Extensible
  • Reusable
  • Readable
  • Poetry

JavaScript already has a concept for that

It’s not a framework, or a library or a new concept and it’s been around since ancient times

Function

The building blocks of programs

var theAllPowerful = function () {
    return 'Bow before me';
}

Functions In JavaScript

The best thing about JavaScript is its implementation of functions. It got almost everything right. But, as you should expect with JavaScript, it didn’t get everything right.

– Douglas Crockford

In order to understand their supremacy, let’s review what functions look like in JavaScript first.

Things You Should Know

Just a brief review of the following.

  • Functions
  • this and arguments keyword
  • call and apply function
  • Closure
  • Recursion

Functions

The bread and butter of programmers

Declaring Functions

There are two primary ways to declare a function.

// Function statement
function greetLucy() {
    return 'Hello Lucile';
}

// Function expression
var greetPatty = function _greetPatty() {
    return 'Hello Sir';
};

// Function Constructor
// We never ever talk or even write this as this is as evil as eval()
// This is just for completion
var greetLinus = new Function ("return 'Sweet Baboo';");

Invoking Functions

There’s three known ways to call or invoke a function.

// Math yo
var add = function _doTheMath(x, y) {
    return x + y;
};

// The canonical function invokation
add(1, 2);

// The functional way of calling functions
// We'll get to this later
add.call(null, 1, 2);

// Same thing above but the arguments is passed as an array
add.apply(null, [1, 2]);

Returning Values

return is the output of the function. If there is no return, an implicit undefined is the output.

function returnSomething(x) {
    return 'I call ' + x.toString();
};

var noReturn = function () {
    // do something
}

console.log(returnSomething('Pikachu')); // out: 'I call Pikachu'
console.log(noReturn()); // out: undefined

Gotcha: Function Hoisting

It is the compiler putting variable/function declarations on top(without your consent)

Consider this snippet consisting of a function statement

doWeirdStuff()

function doWeirdStuff() {
    console.log('Wait, this is declared after it is invoked.');
}

Compare this with the function expression equivalent

doWeirdStuff()

var doWeirdStuff = function theWeirdStuff() {
    console.log('This is the same right? It should also work. Right?');
}

The first one executes, while the other one gives a undefined type error.

Tip

Prefer function expression over function statement to avoid hoisting.

var theLongerWay = function isTheSaferWay() {
    return true;
};

this and arguments

Every function has two implicit variable: this and arguments

var MyModule = {
    whatIsThis: function () {
        // What is?
        console.log(this);

        // And what is
        console.log(arguments);
    }
}

MyModule.whatIsThis(1, 2, 3, 4);
// out(this): MyModule
// out(arguments): [1, 2, 3, 4]

Just this

It is just simply the method’s object

var MyObject= {

    myValue: 'Nyan Cat',

    myMethod: function () {
        console.log(this);
        console.log(this.myValue);
    }
};

MyObject.myMethod();
// out(this): { myValue: 'Nyan Cat', myMethod: function ()}
// out(this.myValue): 'Nyan Cat'

My arguments

An array-like object containing the arguments

var showMeTheEvidence = function (a, b, c) {
    var args = arguments;

    console.log([a, b, c]);
    console.log(args);
}

showMeTheEvidence(1, 2, 3) // out: [1,2,3]
showMeTheEvidence('This', 'is', 'nuts') // out: ['This', 'is', 'nuts']

// Not enough arguments? That' weirdly okay. Javascript is free
showMeTheEvidence({ x: 1 }, true);
// out([a, b, c]): [{x:1}, true, undefined]
// out(arQguments): [{x:1}, true]

// Too many arguments? That's free of charge too
showMeTheEvidence(true, false, 0, 1)
// out([a, b, c]): [true, false, 0]
// out(arguments): [true, false, 0, 1]

Gotcha: arguments is not an array

It is not an array

var extraRicePlease = function (/* args */) {
    var args = arguments;

    args.push('Extra rice');

    console.log(args);
};

extraRicePlease('BBQ', 'Ice Tea');
// expected: ['BBQ', 'ice Tea', 'Extra Rice']
// out: arguments has no method push

Tip

Convert arguments to an array using Array.prototype.slice.call(arguments).

var extraRicePlease = function (/* args */) {
    var args = Array.prototype.slice.call(arguments); // Why must we do this

    args.push('Extra rice'); // Now it works

    console.log(args);
};

extraRicePlease('BBQ', 'Ice Tea');
// out: ['BBQ', 'Ice Tea', 'Extra Rice']

Use can also use the shorter form [].slice.call(arguments).

Gotcha: Function Scoped

Check out this sketch that counts something globally and locally.

var Counter = {
    globalCounter: 0,

    createCounter: function() {
        return {
            localCounter: 0,

            increment: function() {
                this.globalCounter += 1;
                this.localCounter += 1;

                return this.localCounter;
            }
        }
    }
};

var buttonCounter = Counter.createCounter(),
    ajaxCounter = Counter.createCounter();

console.log(buttonCounter.increment()); // out: 1
console.log(ajaxCounter.increment()); // out: 1


console.log(Counter.globalCounter);
// expected: 2;
// out: 0;

Tip

Be careful using this. If you use functions within functions or objects within objects, it is safer to save it in a variable preferrably that or the Pythonic self. Likewise for arguments but very uncommon.

var Counter = {
    globalCounter: 0,

    createCounter: function() {
        var that = this; // Store the parent refrence

        return {
            localCounter: 0,

            increment: function() {
                that.globalCounter += 1; // Correct reference
                this.localCounter += 1;

                return this.localCounter;
            }
        }
    }
};

f.call() and f.apply()

Every function has the method call and apply to invoke them functionally

var fullName = function (firstName, lastName) {
    // return [firstName, lastName].join(' ');
    return firstName + ' ' + lastName;
};

// Normal invokation
console.log(fullName('Francis', 'Murillo')); // out: Francis Murillo

// Using call() without the
console.log(fullName.call(null, 'Mr', 'Robot')); // out: 'Mr Robot'


// Using apply()
console.log(fullName.apply(null, ['Jake', 'Dog'])); // out: 'Jake Dog'

this Argument

The first argument of call and apply sets the this keyword, this is more important for the OO style.

var Mirror = {
    whoAmI: 'Tyler Durden',

    whoAreYou: function (prefix) {
        console.log(prefix + this.whoAmI);
    }
};

var Bad = {
    whoAmI: 'Heisenberg'
};

Mirror.whoAreYou('I am '); // out: 'I am Tyler Durden'

Mirror.whoAreYou.call(Bad, 'You are '); // out: 'You are Heisenberg'

var VeryBad = {
    whoAmI: 'You only need to know mine'
};

Mirror.whoAreYou.apply(VeryBad, ['I do not need to know your name']); // out: awesome

Practical this

Some practical uses of setting the this argument.

var showcaseThis = function (/* args */) {
    var args = arguments;

    // Case: Converting arguments to an array, reasonable
    console.log(Array.prototype.slice.call(this, args));
};

showcaseThis('Clockwork', 'Orange');
// out: ['Clockwork', 'Orange']

// Case: Invoking a "class"/prototype method on an instance
// Why not just "Beethoven".toUpperCase()?
console.log(String.prototype.toUpperCase("Beethoven"));
// out: BEETHOVEN

// Easier to just ['Ode'],concat('to', 'Joy');
console.log(Array.prototype.concat.call(['Ode'],'to', 'Joy'));
// out: ['Ode', 'to', 'Joy']

// Case: Hacking an "private" variable
// Wait for it

Gotcha: Missing this

Consider this quaint way of invoking a method

var Cat = {
    affection: 9007199254740992;, // It is at least over 9000

    pet: function _pettingTheAdorablePuspin() {
        if (this.affection > 50) {
            console.log('purr');
        } else {
            console.log('hiss');
        }
    }
};

var petMethod = Cat.pet;

// Working at the office
// Home and tired, I want to relieve stress. Must pet cat

petMethod();
// expected: 'purr'
// out: 'hiss'

Tip

Be aware if a function needs an object reference or not.

petMethod(); // out: 'hiss'
// Because this.affection is undefined
// undefined > 50 is false
// This should be a type error!?

petMethod.call(Cat); // out: 'purr'

// If you know the object, then why not just invoke it directly
Cat.pet();

For this presentation, we will not use this and invoke call and apply with null as the first argument whenever needed.

Closure

Functions have access to variables to it’s outer function.

var outerFunction = function (outerArg) {
    var outerVar = outerArg + 10;

    return function innerFunction(innerArg) {
        var innerVar = outerVar + innerArg;

        return [outerArg, outerVar, innerArg, innerVar];
    }
}

var newFunction = outerFunction(10);
// outerArg: 10
// outerVar: 20

console.log(newFunction(20));
// out: [10, 20, 20, 40]

console.log(newFunction(100));
// out: [10, 20, 100, 120];

We’ll talk about this more later

Gotcha: Memory Leaks

Not really going to talk about this, but it exists.

setInterval(function myLovelyWidget() {
    var data = []; // Possibly never garbage collected

    fetch('someUrl') // Promise like behavior
        .then(function getAndRender(newData) {
            data = newData;

            // render new data

            // do something else
        });
}, 1000);

Recursion

Calling a function over and over again

// Naive quicksort
var quicksort = function _quicksorter(xs) {
    if (xs.length <= 1) { // Base cases
        return xs
    } else if (xs.length === 2) {
        var first = xs[0],
            last = xs[1];

        return first <= last ? [first, last] : [last, first];
    } else { // Dividing the task
        var pivot = xs[0],
            less = xs.filter(function (x) { return x < pivot; }), // Spoiler Alert
            more = xs.filter(function (x) { return x > pivot; }),
            equal = xs.filter(function (x) { return x === pivot; });

        return []
            .concat(_quicksorter(less))
            .concat(equal)
            .concat(_quicksorter(more));
    }
};

console.log(quicksort([4, 1, 2, 3])); // out: [1, 2, 3, 4]

Calling The Caller

Invoking the parent or calling function using the name given in the function declaration.

var factorial = function _factorer(n) { // Notice the name in the function
    if (n <= 1) { // Base case
        return 1;
    } else { // Induction case
        return n * _factorer(n - 1); // Invoke the parent function
        // return n * factorial(n - 1); // Also okay but relies on external binding
    }
};

console.log(factorial(3)); // out: 3 * 2 * 1 => 6
console.log(factorial(5)); // out: 5 * 4 * 3 * 2 * 1 => 120

Gotcha: Infinite Recursion

Be very careful within recursion as it can cause an infinite recursion with rogue or incorrect input.

var countDown = function _counter(n) {
    if (n === 0) { // Base case
        console.log('Blast off!!');
    } else {
        console.log(n);
        counter(n - 1); // Recursion
    }
};

countDown(3);
// out: 3
// out: 2
// out: 1
// out: 'Blast off!!'

countDown(3.001); // Unhandled case
// out: 3.001
// out: 2.001
// out: 1.001
// out: 0.001 // Where's the smoke?
// out: -0.999 // Wait... when is the rocket launching?
// out: -1.999 // Houston, we have a problem

Tip

Since JavaScript does not support functional programming up front, just be careful when choosing to implement a problem with recursion.

For this presentation, I won’t delve into recursion but for just know and remember you can do recursion… with love and care.

The Power Of Functions In JavaScript

Good design is not about making grand plans, but about taking things apart.

– Rich Hickey

At last, let’s talk about functions.

Functional Programming In JavaScript

I don’t want to bore you with a definition. It’s really just a mindset

  • Input and Output
  • Combining Functions
  • Process over Step
  • Everything is a Function
  • Avoiding State

Why I Like Functional Programming?

  • First principles
  • Easier to write good code
  • Easier to reason
  • Natural and Mathematical
  • Fun and Creative

Why Not OOP?

Christianity has not been tried and found wanting; it has been found difficult and not tried.

– Gilbert Chersterton

  • State
  • Classes are heavyweight
  • Don’t know the prototype system
  • Overrated

What This Is Not

  • A full course in this paradigm
  • A pure functional style
  • An introduction to JavaScript
  • Easy

What This Is

To introduce you to think and write in a functional style can help you write good code in JavaScript and nothing more.

The Idea

What is the most resilient parasite? Bacteria? A virus? An intestinal worm? An idea. Resilient… highly contagious. Once an idea has taken hold of the brain it’s almost impossible to eradicate. An idea that is fully formed - fully understood - that sticks; right in there somewhere.

– Cobb from Inception

The Ideas Of Functional Programming For JavaScript

The whole of the presentation

  • Thinking in terms of collections or as a whole
  • Separating behaviors and combining them
  • Avoiding state with closures

Caveat

You do not have to understand the code, just feel and see that this is much cleaner and better as a whole.

Chapter 1: Thinking With Functions

Let’s talk about lists and their functions namely

Spoilers

  • .forEach
  • .map() & .mapObject
  • .toPairs & .fromPairs
  • .filter & .filterObject
  • .reduce

A Question Of Intent

Who here uses a for loop like so?

var items = ['Hey Arnold', 'Adventure Time', 'JavaScript: The Good Parts'];

for (var i = 0; i < items.length; i += 1) {
    console.log(item[i]);
}

What’s Wrong With For Loops?

Intention

When iterating through an list, one should not be concerned with the length and index of it. All you need is the element and do something with it.

var heroes = [ 'Cloud', 'Tyler', 'Joel'];

for (var i = 0; i < heroes.length; i+= 1) {
    var hero = heroes[i];

    if (hero === 'Tyler') { // The intent
        console.log('Everything is free of charge.');
    }
}

How do we loop over each element without being concerned with the loop mechanics?

No More For Loops

Our journey starts by using the forEach method of an list which allows you to loop through a list given a callback.

var assassins = [ 'Altair', 'Ezio', 'Connor'];

// Use forEach to iterate thorugh a list
assassins.forEach(function getConnor(assassin) { // Give the function a descriptive name
    if (hero === 'Connor') {
        console.log('Where is Charles Lee');
    }
});

Now this looks better, we separated the intention and the looping mechanism is now hidden as an abstraction.

But did you notice we passed a function to another function(the callback).

0th Virtue: Function Variables

The bare minimum that allows JavaScript to be functional is that functions are first class objects meaning you can pass functions as arguments and as variables.

var myHandler = function (x) { // Assigning functions to variables
    return 'You shall not pass';
};

var executeHandler = function (handler) { // A function taking a function
    handler('An ignored value');
}

executeHandler(myHandler); // Passing functions around

If JavaScript did not have this feature, we would not be talking about it.

Implementing forEach

Let’s implement our own forEach for analysis

// Naive implentation
var forEach = function (f, xs) {
    for (var i = 0; i < xs.length; i+=1) {
        var x = xs[i];

        f.call(this,  x);
    }
};

var pi = [3, 1, 4, 1, 6, 1, 8];

// Almost looks the same
forEach(function displayTheNumber(n) {
    console.log(n);
}, xs);

Pretty easy but this demonstrates how passing functions can improve the logic

Transforming Collections

Let’s move on a similar case of transforming the collection.

How about given a list of text, capitalize each one.

var words = ['What', 'Are', 'Words']; // Base list

var upperWords = []; // New list which is just a placeholder

words.forEach(function capitalize(word) {
    var upperWord = word.toUpperCase();

    upperWords.push(upperWord); // Add the value to the list
});

console.log(upperWords); // out: ['WHAT', 'ARE', 'WORDS']

In this case, we want to capitalize the whole list, not capitalize each word in the list.

The Intention

The intention of the problem if we define it as a function.

var capitalize = function theLoopIntention(text) {
    return text.toUpperCase(); // Notice our function has a return
};

What if we can just apply it as a whole instead of defining it?

Using map

Thankfully the map method of lists allows this.

var words = ['What', 'Are', 'Words']; // Base list

var capitalize = function theLoopIntention(text) {
    return text.toUpperCase();
};

// Just like forEach
var newWords = words.map(capitalize);
// or if you want to inline it
// var newWords = words.map(function (word) {
//   return text.toUpperCase();
//  });

console.log(newWords); // Like the last

Again, we have cleanly separated the intention from the loop.

Examples of map

Just some examples to get improve comprehension

var people = [
    { firstName: 'Linus', lastName: 'Van Pelt', nickname: 'Sweet Baboo'},
    { firstName: 'Charlie', lastName: 'Brown', nickname: 'Blockhead' }
];

var getNickname = function (person) {
    return person.nickname;
};

var getFullName = function (person) {
    return person.firstName + ' ' + person.lastName;
};

var capitalize = function theLoopIntention(text) {
    return text.toUpperCase();
};


// Case: Getting a property from a list of objects
console.log(people.map(getNickname)); // out: ['Sweet Baboo', 'Blockhead']

console.log(people // You can chain maps by the way
            .map(getFullName)
            .map(capitalize)); // out: ['LINUS VAN PELT', 'CHARLIE BROWN']

Implementing map

Just like with forEach, implenting the map is easy.

var map = function (f, xs) {
    var ys = [];

    xs.forEach(function (x) {
        var y = f(x);

        ys.push(y);
    });

    return ys;
};

var wrapAsText = function (x) {
    return '<p>' + x + '<p/>';
};

var labels = ['First Name', 'Last Name'];

console.log(map(wrapAsText, labels));
// out: ['<p>First Name</p>', '<p>Last Name</p>'];

Again we separated the intention from the implementation. Isn’t this a recurring theme?

1st Virtue: Input And Output

The user of the function should only be concerned with the input and output, not how it is done. It is transforming the inputs to produce the output.

In the case of map, given a list and a transformation function, return a transformed list. You should not care how it did it, be it a for loop or a forEach function or a recursion.

This is both hard to explain and do. Let’s demonstrate this with the next concept.

Objects As Collections

You can think of objects as a collection of key value pairs

var object = {
    'cowboy': 'bebop',
    'stein': 'gate',
    'summer': 'wars'
};

var objectPairs = [
    ['cowboy', 'bebop'],
    ['stein', 'gate'],
    ['summer', 'wars']
];

So why should it matter? Patience, let’s define what pairs are.

Pairs

Pairs are just lists with two elements. Easy, right?

var numberPair = [100, 20],
    stringPair = ['Satoshi Kon', 'Tokyo Godfathers'],
    keyValuePair = ['key', { subObject: 1}],
    pairInPairs = [[1, 2], [3, 4]]; // Not going to go that far

var numericTriple = [1, 2, 3], // Three elements
    singleString = ['Working!!!'];   // One element

Objects As Pairs

Let’s create a function to convert an object to a list of key value pairs

// Assuming we don't have Object.keys
// This returns the keys of an object
var keys = function (object) {
    var keys = [];

    for (var key in object) {
        if (object.hasOwnProperty(key)) {
            keys.push(key);
        }
    }

    return keys;
};

// Making the get a function
var get = function (key, object) {
    return object[key];
};

// Converts an object to a list of key value pair
var toPairs = function (object) {
    return keys(object)
        .map(function covertToPair(key) {
            var value = get(key, object);

            return [key, value];
        });
};

Using toPairs

Just a demonstration.

toPairs({
    number: 1,
    text: 'meow',
    isSomething: true,

    recurse: {
        A: 'a',
        B: 'b'
    }
})
/*
  out: [
  ['number', 1],
  ['text', 'meow'],
  ['isSomething', true],
  ['recurse', {
  A: 'a',
  B: 'b'
  }]]
  ]
*/

Pairs As Objects

Let’s create a function to do the opposite: convert a function

// Let's wrap the set of objects as a function
var set = function (key, value, object) {
    object[key] = value;

    return object;
};

var fromPairs = function (pairs) {
    // The recursive version is much more functional but not necessarily better
    var newObject = {};

    pairs.forEach(function (pair) {
        var key = pair[0],
            value = pair[1];

        set(key, value, object);
    });

    return newObject;
};

So what does it mean to think of objects as pairs?

Objects As A Whole

What if you had an object and want to capitalize every string?

What if we could map over over objects as we do with lists?

var formData = {
    firstName: 'Linus',
    lastName: 'Van Pelt',
    age: 20
};

var tryUppercase = function _intention(value) {
    return (typeof value === 'string') ? value.toUpperCase() : value;
}

var mapObject = function (f, object) {
    // ???
};

mapObject(tryUppercase, formData);
/* expected:
   {
   firstName: 'LINUS',
   lastName: 'VAN PELT',
   age: 20
   }
 */

Of course we can.

Implementing mapObject

Using all we made so far

// A naive implementation to use all we have
var mapObject = function (f, object) {
    var mappedPairs = toPairs(object) // Step 1: Convert to pairs
        .map(function (pair) {
            var key = pair[0],
                value = pair[1],
                newValue = f(value, key); // Step 2: Map over the value

            return [key, newValue]; // Can be more succinct
        });

    return fromPairs(mappedPairs); // Step 3: Convert to object
};

Notice how we transform the object to pairs and back again. This demonstrates the first virtue.

Another Example of mapObject

What if we want to find the differences between an old and new object?

var diff = function (oldObject, newObject) {
    return mapObject(function (oldValue, key) {
        var newValue = newObject[key];

        return oldValue !== newValue;
    }, oldObject);
}

var oldData = { company: 'Outbreak Comapny', position: 'Ambassador', gender: 'male'},
    newData = { company: 'IT Outsourcing', position: 'Ambassador', gender: 'male'};

var diffData = diff(oldData, newData);

console.log(diffData);
/* out:
   { company: true, position: false, gender: false }
*/

if (diffData.company) { // Compare with oldData.company !== newData.company
    // Do something when the company changes
}

Shrinking Collections

Let’s move on to filtering collections given a criteria.

Say we have a list of movie titles and we only want the James Bond films.

var films = {
    { name: 'Moonraker', category: 'James Bond'},
    { name: 'Sucker Punch' category: 'Action'},
    { name: 'Casino Royale', category: 'James Bond'}
};

var isJamesBondFilm = function _predicateIntention(film) {
    return film.category === 'James Bond';
};

whatFunctionIsThis(isJamesBondFilm, films);

There is a function for lists called filter that can get our job done

Using filter

Given a predicate or a boolean function and a list, return a new list where the predicate is true over the list.

// Some trivial examples
var numbers = [1, 2, 3, 4, 5];

var isOdd = function (number) {
    return number % 2 === 1;
};

var isTheOne = function _heyJetLi(number) {
    return number === 1;
};


console.log(numbers.filter(isOdd)); // out: [1,3,5]
console.log(numbers.filter(isTheOne)); // out: [1]

So we have another way to work with lists.

Implementing filter

Again, we implement this for our own benefit.

// Another naive
var filter = function (p, xs) {
    var ys = [];

    forEach(function _checkPredicate(x) {
        var y = x; // Just to get the name right with ys

        if (p(x)) {
            ys.push(y);
        }
    });
};

var isLowerCase = function (text) {
    return text.isLowerCase() === text;
};

var vendors = ['TORGUE', 'Hyperion', 'dahl'];

console.log(filter(isLowerCase, vendors)); // out: ['dahl']

So we have another trick to use with lists. However, this trick has two other concepts attached to it.

First Thing: Nested Ifs

Who here likes nested if statements?

var a === true;

if (a) {
    // One if is okay
}

var b === false;

if (!a) {
    if (b) {
        // Two ifs and you might want to refactor this if you can
    } else {
    }
}

var c === false;

if (!c) {
    if (!b) {
        if (!a) {
            // Who the hell will write this?
        }
    }
}

I don’t like branching, it’s too easy to do and easy to make the code more complicated to reason about with too many ifs.

Code Review

Consider this code as an example of nesting ifs. Given a list of books that are to be processed and a book isbn table, find all the unprocessed books without an isbn

var books = [
    { name: 'The Picture Of Dorian Gray', processed: false},
    { name: 'Minecraft For Dummies', processed: true},
    { name: 'Functional Programming In Javascript', processed: false}
];

var bookIsbnTable = {
    'The Picture Of Dorian Gray': '1234',
    'Minecraft For Dummies': '2344',
    'Skyrim: The Official Guide': '3450'
}

var booksWithoutIsbn = [];

books.forEach(function (book) {
    if (!book.isProcessed) {
        var isbn = get(book.name, bookIsbnTable);

        if (!isbn) {
            booksWithoutIsbn.push(book);
        }
    }
})

Let’s refactor this to get to my point

Refactor 01: Separate Intentions

Separate the main intentions

var books = [ /* ... */];

var bookIsbnTable = { /* ... */ };

// Intentions
var isProcessed = function (book) {
    return book.isProcessed === true;
};

var hasNoIsbn = function (book) {
    var isbn = get(book.name, bookIsbnTable);

    return !isbn;
}

var booksWithoutIsbn = [];

books.forEach(function (book) {
    if (isProcessed(book)) {
        if (hasIsbn(book)) {
            booksWithoutIsbn.push(book);
        }
    }
})

Refactor 02: Use Filter

Let’s remove the first if statement using the new found filter power

var books = [ /* ... */];

var bookIsbnTable = { /* ... */ };

// Intentions
var isProcessed = function (book) {
    return book.isProcessed === true;
};

var hasNoIsbn = function (book) {
    var isbn = get(book.name, bookIsbnTable);

    return !isbn;
}

var booksWithoutIsbn = [];

books
    .filter(isProcessed) // The if statement becomes a transformation
    .forEach(function (book) {
        if (hasNoIsbn(book)) { // Just one if left
            booksWithoutIsbn.push(book);
        }
    });

We removed one if, can we remove the other?

Refactor 03: Use Filter Again

We can chain the filter to remove the other if

var books = [ /* ... */];

var bookIsbnTable = { /* ... */ };

// Intentions
var isProcessed = function (book) {
    return book.isProcessed === true;
};

var hasNoIsbn = function (book) {
    var isbn = get(book.name, bookIsbnTable);

    return !isbn;
}

var booksWithoutIsbn = [];

books
   .filter(isProcessed)
   .filter(hasNoIsbn) // We not have a filter chain
   .forEach(function (book) { // This is somewhat awkward to have
       booksWithoutIsbn.push(book);
   });

And maybe we can remove the awkward forEach here

Refactor 04: Just filter

We just let the filter chain be the result and we’re done

var books = [ /* ... */];

var bookIsbnTable = { /* ... */ };

// Intentions
var isProcessed = function (book) {
    return book.isProcessed === true;
};

var hasNoIsbn = function (book) {
    var isbn = get(book.name, bookIsbnTable);

    return !isbn;
}

var booksWithoutIsbn = books
    .filter(isProcessed)
    .filter(hasNoIsbn);

Although contrived, we just eliminated the if statements with the filter function.

Avoiding Ifs With filter

Notice how the code is much more readable and easier to understand without the explicit ifs?

var booksWithoutIsbn = books
    .filter(isProcessed)
    .filter(hasNoIsbn);

The other thing about this is that the if is a process flow or a transformation over the list, not as a branching logic.

Also notice that if someone wants to add another condition, they are more likely to add another filter to the chain and less likely to just hack the if condition.

Second Thing: Filter Collections

If objects are also collections, then couldn’t we filter over them as well?

For example, we want to remove all null or undefined in an object so that we can pass it over the wire.

var ajaxData = {
    email: 'francisavmurillo@gmail.com',
    age: null,
    gender: 'male',
    birthday: null
}

var isData = function (value) {
    return value != null || value != undefined || value != '';
};

console.log(filterObject(isData, ajaxData)); // filterObject???
/* out:
   {
   email: 'francisavmurillo@gmail.com',
   gender: 'male'
   }
*/

You already know it is.

Implementing filterObject

I can’t believe this is too easy.

var filterObject = function (p,  object) { // Just like mapObject
    var filteredPairs = toPairs(object)
      .filter(function (pair) { // Notice map is just replaced with filter
          var key = pair[0],
            value = pair[1],

            return p(value, key); // We apply the predicate here
      });

    return fromPairs(filteredPairs);
}

Using filterObject

How about a contrived example?

var request = {
    _method: 'POST',
    _csrf: 'abcde',
    someData: 1
};

var isUnderscored = function (text) {
    return text[0] === '_';
};



console.log(filterObject(function (value, key) {
    return isUnderscored(key);
}, request));

/* out: {
   _method: 'POST',
   _csrf: 'abcde'
   }
*/

But filtering by keys is not my point.

2nd Virtue: Data Abstraction

By thinking about the operations over data, we can abstract the behavior to other containers.

var f = function (x) {
    // Do something with x
}

mapX(f, xs); // What is xs? What if xs is a Promise, an Observable
filterX(f, xs); // Sometimes we don't really care

Again the process matters more than the data. If there was another data type the same ideas can come into place.

Collecting Collections

Finally, we move on to collecting or aggregating all the values of an collection.

For example, given a list of numbers, return their sum

// You're probably getting the picture or getting bored
var numbers = [1, 2, 3, 4, 5];

var sum = 0;

var add = function (a, b) {
    return a + b;
};

numbers.forEach(function (number) {
    sum = add(sum, number);
});

console.log(sum);

We have the reduce function for this

Using reduce

reduce takes a combining function and a list and returns the combined values of the list.

var numbers = [1, 2, 3, 4];

var add = function _theRealIntent(a, b) {
    return a + b
};

var sum = numbers.reduce(function _combiningFunction(acc, number) { // Explain this bro
    // acc is the accumulated value
    // number functions as the number in the list
    return acc + number;
}, 0);
// var sum = numbers.reduce(add, 0); // Better, once you understand combining operations

console.log(sum); // out: 10

Let’s implement this like the other two

Implementing reduce

Once you implement it, the idea of combining function is easy

var reduce = function (oper,  initialValue,  xs) {
    var currentValue = initialValue;

    forEach(function combine(x) {
        // Combine the currentValue and the next
        currentValue = oper(currentValue, x);
    });

    return totalValue;
};

Let’s have the usual examples

Examples of reduce

Some basic examples of reduce

var numbers = [1, 2, 3, 4];

var multiply = function (x, y)  {
    return x * y;
};

console.log(numbers.reduce(multiply, 1)); // out: 1 * 1 * 2 * 3 * 4 = 24
console.log(numbers.reduce(multiply, 5)); // out: 5 * 1 * 2 * 3 * 4 = 120

How about some real examples?

A More Specific find

Sometimes in a list, you want to find a specific value given a criteria or predicate.

We can implement this using filter but we can also implement it using reduce.

var find = function (p, defaultValue, xs) {
    return xs.reduce(function (prev, next) {
        return p(next) === true ? next : prev;
    }, defaultValue);
};

var findWithFilter = function (p, defaultValue, xs) {
    var foundValues = xs.filter(p);

    return foundValues.length > 0 ? foundValues[0] : defaultValue;
};

var isTheMeaningOfLife  = function (number) {
    return number === 42;
};

console.log(find(isTheMeaningOfLife, 0, [36, 42, 48])); // out: 42
console.log(find(isTheMeaningOfLife, 0, [37, 43, 49])); // out: 0, the default value

A Deep Getter

Imagine you have an deep object and you want to access an inner object and don’t want to deal with undefined types exception. We can make a safe getter for that.

var deepGetter = function (deepKey, object) {
    var keys = deepKey.split('.');

    return keys.reduce(function _deepGet(currentObject, key) {
        var newObject = get(key, currentObject);

        return newObject === null || newObject === undefined ?
            undefined : newObject;
    }, object);
};

var deepObject = {
    a: {
        b: {
            c: 1
        }
    }
};

console.log(deepGetter('a.b.c', object)); // out: 1
console.log(deepGetter('a.d', object)); // out: undefined

What Does reduce Mean For Us

If you have a list and want an aggregated value, the reduce should be a natural choice. It allows you think in terms of combining the values instead of hacking around at computing it.

We’ll get back to this function later.

Combining All Three

Given a list of people, find all the people that are not minors and compute the total.

var people [
    { name: 'Mr Midnight', age: 20, salary: 50},
    { name: 'Mr Muffin', age: 25, salary: 60},
    { name: 'Ms Pepper', age: 17, salary: 40}
];

var isNotAMinor = function (person) {
    return person.age >= 18;
}

var getSalary = function (person) {
    return person.salary;
}

var add = function (x, y) {
    return x + y
}

console.log(people
            .filter(isNotAMinor)
            .map(getSalary)
            .reduce(add)); // Nice to see the three working together

Quick Review

Just a quick review of everything we’ve done.

  • Think in terms of input and output
  • Separate the intention from the implementation
  • map, filter and reduce should be your best friends
  • Process over data

Chapter 2: Combining Functions

Let’s get to the fun stuff

Spoilers

  • compose & pipe
  • curry

3rd Virtue: Functions As Units Of Behavior

Functions represents behavior or what we have been calling intentions.

Primarily, a function should represent a process and not be tangled with other details

A Simple Event

Let’s say we have two buttons with their corresponding handlers.

var buttonHandler = function () {
    console.log('This button does something awesome');
}

var otherButtonHandler = function () {
    console.log('This button does something way better than the other one');
}

All is well

Adding A Counter

Now, what if we want to track send information to the server that a button was clicked? Let’s say we have a sendClick function that sends data to the server.

var sendClick = function () { /* whatever */}

var buttonHandler = function () {
    sendClick(); // Dirty

    console.log('This button does something awesome');
}

var otherButtonHandler = function () {
    sendClick(); // What the hell are you doing here?

    console.log('This button does something way better than the other one');
}

But this implementation is dirty, copy pasting a method for each handler and it ruins the fact the handler should be concerned with sending logging data or what have you.

Simple Function Over Functions

What we want is to separate the handler from the logging. What we want is to execute a function before the main one.

Let’s call warm up with this doBefore function combiner, we will finally use apply to invoke the functions.

var doBefore = function (before, main) {
    return function _executor(/* args */) { // A function that combines functions
        var args = [].slice.call(arguments);

        before.apply(null, args); // Execute the function before

        return main.apply(null, args); // Execute the main function
    }
}

Let’s use this in our example

Using doBefore

Let’s see how it makes the code much better

var sendClick = function () { /* whatever */}

var buttonHandler = doBefore(sendClick, function () { // Wrapping the handlers
    console.log('This button does something awesome');
}); // This functions returns the combined function

var otherButtonHandler = doBefore(sendClick, function () {
    console.log('This button does something way better than the other one');
});

Notice our handlers are just the same except they are now wrapped with the logging function. This is what it means to combine and separate behaviors.

Reflection: Higher Order Functions

How many times have you copy pasted a block of function to several places without consideration for it’s purpose or intent?

If we cleanly separate the intentions of our code and combine them properly, we can get easy to read and understand code.

What we just did is make an higher order function but that’s just definition.

Another Warm Up: Preventing Execution

What if instead of executing before, we prevent the execution of the next one?

For example, if you have a button and you want to allow the event to continue if the user has enough privilege or what have you.

var executeIf = function (checkIf, main) {
    return function (/* args */) {
        var args = [].slice.call(arguments);

        // Check the condition
        if (checkIf.apply(null, arguments) === true) {
            return main.apply(null, arguments);
        }
    }
};

var checkWhatever = function (/* args */) { // Check for something
    console.log('You shall not pass');
    // alert('You shall not pass'); // also works

    return false;
};

var buttonHandler = executeIf(checkWhatever, function () {
    console.log('Button has been clicked');
});

Again the code to glue the two functions together is cheap and easy.

One More Appetizer: Preventing Too Many Clicks

How about we prevent a button being pressed in a short burst, could be useful for submit buttons

var debounce = function (f, delay) { // I didn't come up with debounce
    var blockInvokations = false; // Using closures here, spoilers

    return function (/* args */) {
        var args = [].slice.call(arguments);

        if (blockInvokations === false) {
            blockInvokations = true; // Block succeeding invokations

            setTimeout(function _unblock() { // Unblock it after the delay
                blockInvokations = false;
            }, delay);

            return f.apply(null, arguments); // Execute normally
        } else {
            // Can't execute yet, got to wait
            return undefined;
        }
    }
};

var buttonHandler = debound(function _actualHandler() {
    console.log('You just paid some website some electronic cash');
}, 300); // 300 is a magic number

A little more complicated but it does show how the we can separate concerns or behaviors

Learning To Compose

Once you understand that you can join functions together, you can create a pipeline using functions.

Let’s start with an simple problem of uppercasing every text field in an object then converting into JSON.

var isText = function (text) {
    return typeof text === 'string';
}

var objectToUpperCase = function (object) {
    return mapObject(function (value) {
        return isText(value) ? value.toUpperCase();
    }, object);
};

var objectToJson = function (object) {
    return JSON.parse(object);
};

var data = { name: 'Muffin', breed: 'Puspin', age: 4 };

var output = objectToJson(objectToUpperCase(data)); // The end result
// But I shouldn't care about toJson or toUpperCase

Better if the two functions can be joined as one intention, objectSerialize?

A Messy Invokation

Just to demonstrate the extra parenthesis are not just dirty, but harder to read and maintain

// Imagine you have three weird functions
var x = function (v) {/* ... */},
    y = function (v) {/* ... */},
    z = function (v) {/* ... */};

var a = null;

// This is ugly
var b = x(y(z(a)));

var t = function (v) {
    return x(y(z(v)));  // Better hide the mess like a guy
};

// Better but kinda hacked
var c = t(a);

What we really care about is c, not x, y, or z. What we need is something to tie the pipeline.

Introducting compose

So the function we’re looking for compose, given two functions it will call the second one with the arguments and pass it’s output to the first function and be the function of the return value.

Easier to explain with code. Remember we want to remove the ugly wrapping of parenthesis in function invokation.

var compose = function (outer, inner) {
    return function (/* args */) {
        var args = arguments;

        var firstValue = inner.apply(null, args);
        // First, invoke the inner function

        var nextValue = outer.call(null, firstValue);
        // Then invoke the outer function with the return value as the argument

        return nextValue;
    };
},

Let’s see this in our example above

Using compose

Let’s join those two functions in with compose

var objectToUpperCase = function (object) {
    // ...
};

var objectToJson = function (object) {
    // ...
};

// Tying the two functions together, looks cleaner than before
var objectSerialize = compose(objectToJson, objectToUpperCase);
// Remember to read from right to left in order of execution

var data = {
    // ...
};

console.log(objectSerialize(data));

We successfully removed those wonky parenthesis but how else can compose help us in our journey of better code.

Examples of compose

Let’s get acquainted with our new friend, make it your BFF if you can.

// Mathematical Examples
var square = function (n) { return n * n; },
    increment = function (n) { return n + 1; },
    decrement = function (n) { return n - 1; },
    display = function (n) { console.log(n); return n; };

var nextSquare = compose(square, increment),
    incrementTwice = compose(increment, increment),
    addZero = compose(decrement, increment),
    displaySquare = compose(display, square);

Composing is better when you start using it with closures and currying. But for now, how do we compose more than two functions?

Improving compose

So how do we compose functions all the way to the moon?

// Three functions
var escapeHtml = function (text) { /* ... */ },
    wrapAsText = function (text) { /* ... */ },
    wrapInDiv = function (text) { /* ... */ };

var data = ['5 Centimeters Per Second', 'Garden Of Words'];

// Plural compose, composes.
var htmlizer = composes( // Three compositions
    wrapInDiv,
    wrapAsText,
    escapeHtml); // Do note, that this seems declarative on the process

// Hypothetical scenario in converting a list into Html text
console.log(data
            .map(htmlizer)
            .join('\n'));

First, we go back to our old friends

Some Backups

Let’s implement a few things to improve the readability of our grand composes

// Returns an reversed version  of the list
var reverse =  function (xs) {
    var nxs = xs.slice(); // Shortcut for copying an array
    nxs.reverse(); // Mutates the array

    return nxs;
};

// Returns the first element of the list
var first = function (xs) {
    return get(0,  xs); // or just xs[0] if you are in a hurry
}

// Likewise the rest of the lements of the list
var rest = function (xs) {
    return xs.slice(1);
};

// Just a reduce with the initial value being the first value in the list
var reduceFirst = function (oper, xs) {
    var initialValue = first(xs),
      otherValues = rest(xs);

    return reduce(oper, initialValue, otherValues);
};

One More Thing

I prefer to read left to right instead of right to left with my function pipeline.

var pipe = function (first, next) {
    return compose(next, first);
};

var splitWords = function (sentence) { return text.split(''); },
    splitParagraphs = function (doc) { return text.split('\n'); };

// Originally
var getWords = compose(splitWords, splitParagraphs);

// Really, notice the sequence is read left to right
var getWords2 = pipe(splitParagraphs, splitWords);

This is just compose with the arguments reversed which might be a small thing but helps in readability, just my prefrence anyway.

Implementing composes

With that out of the way, we simply use reduceRight and pipe in one master stroke

var composes = function (/* fs */) {
    var fs = [].slice.call(arguments);

    // You can use compose instead of pipe but you would have to reverse the arguments
    return reduceFirst(pipe, reverse(fs));
};

That’s how easy it is to implement composes.

Equivalently pipes

Just for the sake of symmetry.

var pipes = function (/* fs */) {
    var fs = [].slice.call(arguments);

    return reduceFirst(pipe, fs); // This is just without the reverse
}

Now let’s see how they fit together.

Checking Out composes

Let’s check it out.

var twice = function (n) { return n * 2; },
    half = function (n) { return n / 2; },
    increment = function (n) { return n + 1; };

var sequence = composes(half, twice, increment);

var sequence2 = pipes(increment, twice, half, twice);

var sequence3 = pipes( // Preferred way of writing
    increment,
    twice,
    half,
    twice
);

Viola, we can compose as much as we want. But where does this leave us?

Function Pipelines

It’s not the fact that you use compose or pipe, but rather that you want your code to be a single and straight process.

For example, displaying data in html. The process you want is.

  • Source
  • Map
  • Render

But we tend to diverge from this as we add more features. The point is you want to maintain the integrity of the process.

Avoiding Ifs With Composition

Let’s have another case review. Given a list of employees and there salary, let’s compute their take home pay.

var codeCats = [
    { name: 'Mr. Muffin', salary: 100, gender: 'male'},
    { name: 'Ms. Fuzbudget', salary: 50, gender: 'female'}
];

var payComputer = function (codeCat) {
    var pay = codeCat.salary / 2;

    return set('pay', pay, codeCat);
};

console.log(codeCats.map(payComputer));

All is fuzzy and warm

Gender Inequality

Now what if every female employee gets paid 50% more due to a goverment law. What do you do to make it right?

var codeCats = [
    { name: 'Mr. Muffin', salary: 100, gender: 'male'},
    { name: 'Ms. Fuzbudget', salary: 50, gender: 'female'}
];

var payComputer = function (codeCat) {
    var pay = codeCat.salary / 2;

    var newerPay = codeCat.gender === 'female' ? pay * 1.5 : pay;

    return set('pay', newerPay, codeCat);
};

console.log(codeCats.map(payComputer));

Not a problem, but what if you can’t modify payComputer because it’s a third party shiznit? Or what if there is another law, are we going to add another if?

You know where this is going.

Composition To The Rescue

Let’s use composition to make the code cleaner.

var codeCats = [
    { name: 'Mr. Muffin', salary: 100, gender: 'male'},
    { name: 'Ms. Fuzbudget', salary: 50, gender: 'female'}
];

var femalePayRaise = function (codeCat) {
    var basePay = codeCat.pay; // Must already be paid

    return set('pay', codeCat.gender === 'female' ? basePay * 1.5 : basePay, codeCat);
};

var payComputer = compose( // Process is maintained
    femalePayRaise,
    function _originalComputer(codeCat) {
        var pay = codeCat.salary / 2;

        return set('pay', newerpay, codeCat);
    });

console.log(codeCats.map(payComputer)); // Still well

We retain the original intent and managed complexity.

Reflection: Compose Behaviors

Although the example is quite contrived, the main point is to avoid complexity and maintain the simplicity of the process.

The thinking style should be a composition pipeline. A straight flow is better than a branching sewer.

As a tip, whenever there is a new functionality or rule, consider composition or the like to manage the complexity.

Learning To Curry

Currying is a nice functional idea to sweeten composition

Consider this multiplication function, what if we want the first argument to be preset.

var multiply = function (x, y) { return x * y; }

// What if we want have the following?
var multiplyByTwo = function (y) { return multiply(2, y); },
    multiplyByFive = function (y) { return multiply(5, y); };

// There is a sort of duplication here. How about?
var multiplyPreset = function (x) { // Neat little trick
    return function (y) { // Return a function where the first argument is preset
        return multiply(x, y); // Execute the actual function with the arguments
    };
};

// Same as above but notice we removed the noise in declaring the functions?
var multiplyWithTwo = multiplyPreset(2),
    multiplyWithFive = multiplyPreset(5);

console.log(multiplyWithFive(4)); // out: 20
console.log(multiplyWithTwo(2)); // out: 4

The Neat Trick

Let’s have another example with a function that takes three arguments

// Consider an function that add triples
var addTriple = function (x, y, z) { return x + y + z; };

// Let's repeat the neat little trick
var addTriplePreset = function (x) {
    return function (y) {
        return function (z) { // Looks kinda coo
            return addTriple(x, y, z);
        };
    };
};

var addTen = addTriplePreset(10);

console.log(addTen(4, 5)); // out: 19

var addTenAndFive = addTriplePreset(10)(5);

console.log(addTenAndFive(6)); // out: 21

Naming The Trick

But this seems to be a function behavior, not logic. Maybe we can separate this behavior.

var curry = function (f) { // Thanks Haskell Curry
    /* ??? */
};

// Let's curry our get function
// get takes the key and the object
var getId = curry(get)('id'); // or function (object) { return get('id', object); }

var users = [
    { id: 1, username: 'Beethoven'},
    { id: 2, username: 'Mozart'},
    { id: 3, username: 'Ravel'}
];

console.log(users.map(getId)); // out: [1,2,3];

console.log(users.map(function _getId(user) { // Compare with this
    return get('id', user);
}));

Let’s implement the easy version

Currying For Two

Copy pasting our trick from before

var curry = function (f) {
    return function (x) {
        return function (y) {
            return f.apply(null, [x, y]); // or f(x, y);
        }
    }
};

This is enough but what if you want to implement it for three arguments or four? You could copy paste the same definitions over and over.

But there is a better way.

Implementing curry

This is the most fun and challenging to code but the main concept is to keep returning a function until enough arguments have been supplied and then invoke it.

var curry = function _recursiveCurry(f) {
    // Get the number of arguments in a function
    var numberOfArgs = f.length;

    // An helper function to curry the original function
    var currier = function _recursiveCurry(previousArgs) {
        return function _curried(/* currentArgs */) {
            var currentArgs = [].slice.call(arguments),
                newArgs = previousArgs.concat(currentArgs);

            // If there is enough args, invoke the function
            if (newArgs.length >= numberOfArgs) {
                return f.apply(null, arguments);
            } else { // If there is not enough args yet, keep currying
                return _recursiveCurry(newArgs);
            }
        };
    };

    return currier([]); // Start recursion with no arguments
};

This is the only thing that looks complicated, I swear.

Using curry

Just a contrived use of the generic curry

var computeName = curry(function _fullName(firstName, lastName) {
    return firstName + ' ' + lastName;
});

var doctorName = computeName('Doctor');

console.log(doctorName('Death')); // out: Doctor Death
console.log(doctorName('Who')); // out: Doctor Who

var johnName = computeName('John');

console.log(johnName('Marshton')); // out: John Marshton
console.log(johnName('Doe')); // out: John Doe

// Cute tricks with it, but don't do this
console.log(computeName('Linus')()('Van Pelt')); // out: Linus Van Pelt
console.log(computeName()()()('Linus', 'Van Pelt')); // out: Linus Van Pelt

But where does this fit in with compose?

The Real Trick

Curry a function until it has one argument left which you can pass through a composition or mapping pipeline.

var heroes = [
    { name: 'Yang Xiao Long', team: 'RWBY'},
    { name: 'Ruby Rose', team: 'RWBY' },
    { name: 'Pyrrha Nikos', team: 'JNPR'}
];

var setHealth = curry(set)('hp', 100),
    setScore = curry(set)('score', 0);

console.log(heroes
            .map(setHealth)
            .map(setScore));

// or if you care about performance
var setStats = compose(setHealth, setScore); // or pipe(setScore, setHealth);

console.log(heroes.map(setStats));
// Did I declare a function??

Doesn’t it look nice? We just created new functions from old ones and given them more specific uses.

Currying And Filtering

How about using it in conjuction with filter? Given a list of heroes, I want to filter the intelligence type heroes in the list or team.

var heroes = [
    { name: 'Pudge', type: 'STR', kills: 15},
    { name: 'Puck', type: 'INT', kills: 13},
    { name: 'Lich King', type: 'INT', kills: 9}
    { name: 'Razor', type: 'AGI', kills: 4},
    { name: 'Ogre Magi', type: 'STR', kills: 1}
];

var eq = curry(function _equals(a, b) {
    return a === b;
});

var getType = curry(get)('type'),
    isInt = eq('INT');

var isIntType = pipe(getType, isInt);

console.log(heroes.filter(isIntType));

// compare with, I leave it to you which is better
console.log(heroes.filter(function _isIntType(hero) {
    return heroes.type === 'INT';
}));

Still cool

Fixed Options

Let’s say you have a third party component componentBuilder and the a web page has a whole lot of it. You can curry the builder with the options required and let it be the function that builds it to serve as a function interface.

// The third party builder function
var componentBuilder = function (options, element) {
    /* ... */
};

// The options for the page
var pageOptions = {
    /* ... */
}

// I don't care about the options, just build it when I give it to you
var buildComponent = curry(componentBuilder)(pageOptions);

var domComponents = [
    document.getElementById('period'),
    document.getElementById('type'),
    document.getElementById('projects')
];

// Just build it for each of this
domComponents.forEach(buildComponent);

I Want My Modules Curried

I love currying functions that all my functions in my module should be curried by default.

var isTypeOf = curry(function (type, value) {
    return typeof value === type;
});

var isFunction = isTypeOf('function');


var invokeIf = curry(function (pred, f, value) {
    return pred(value) ? f(value) : value;
});


var autoCurry = curry(mapObject)(invokeIf(isFunction, curry));

var Module = autoCurry({
    doThis: function (a, b) { console.log([a, b]); }
});

Module.doThis(1)('b'); // out: [1, 'b']

4th Virtue: Everything Should Be A Function

With higher ordered concepts like composition and currying, if everything is a function then all of them benefit from higher order abstractions.

Now you know why get and set are functions so that they can be curried and composed.

There are other higher order functions that sweeten the deal.

Quick Review

So those are my fundamental tricks.

  • compose, pipe and curry are fun tools to implement and have
  • Combining functions are easy
  • Making new functions from old are easy

Chapter 3: State Of Functions

This last section is much more concerned with the philosophy of this paradigm

Spoilers

  • Closures
  • Immediately Invoked Function Expressions(IIFE)

A Question Of Design

Does anyone know the output of this snippet?

var games = ['Tetris', 'Pong', 'Mortal Kombat'];

// Sort the list
var sortedGames = games.sort());

console.log(sortedGames);

The sorted list but there is something else afoot here.

console.log(games === games.sort());

This returns true. The list is sorted in place, so they’re the same. This is what is known as a side effect.

Side Effects

This is simply something that changes when the function is invoked. This is also known as state mutation.

var counter = 0;

var sum = function (numbers) {
    counter += 1; // State mutation or side effect

    return reduceFirst(function (a, b) { return a + b; }, numbers);
};

console.log(counter); // out: 0

// We didn't pass in counter...
console.log(sum([1,2,3])); // out: 6

// ... yet why is it changed without my conset
console.log(counter); // out: 1

A Function Of Trust And Reason

How do you know if a function has side effects? How do you know if the parameters aren’t manipulated or changed without your consent?

The main point is that it is harder to reason about code or understand when it changes something outside it’s scope or function.

Side effects aren’t bad, we just want to minimize it if we can.

5th Virtue: (Almost) No Side Effects

Functions should (almost) never do the following

  • Mutate the parameters
  • Mutate global state
  • If you do mutate, make it explicit or known
  • If you do need state, we have closures for that

This is the hardest to follow. If you notice yourself making state or mutating variables, consider the consequences..

Closures: Revisited

What closures really are is that they remember the environment, scope or variables.

var rememberThis = function (value) {
    var rememberMe = value; // This value will exist until function does

    return function () {
        return rememberMe; // It remembers me
    };
};

var rememberTheDate  = rememberThis('Fifth Of November');

// Several bad puns later

console.log(rememberTheDate()); // out: Fifth Of November

Here is the fun bit: can you change the value of rememberMe directly?

Closures And State

Closures are really state for functions.

var incrementer = function (startValue) {
    var currentValue = startValue; // Function state

    return function () {
        // The value is increased each time it is called
        currentValue += 1; // Mutate the state

        return currentValue;
    };
};

var increasingSequence = incrementer(0);

console.log(increasingSequence()); // out: 1
console.log(increasingSequence()); // out: 2
console.log(increasingSequence()); // out: 3

This is a form of state mutation that is well contained within the function. Nobody can access currentValue directly.

You can create lazy sequences with this technique.

Private Variables With Closure

Closures can provide what is known as private variables to OOP

// Creating an entity with function closure
var person = function (initialName, initialGender) {
    var currentName = initialName,
        currentGender = initialGender;

    // This time we return an object that interacts with the closure
    return {
        getName: function () { return currentName; },
        getGender: function () { return currentGender; },

        // Prefer to make a new copy but to show state here
        setName: function (newName) { currentName = newName; },

        // There is no change gender function
    };
};

var me = function ('FnMurillo', '♂');

console.log(me.getName()); // out: FnMurillo
console.log(me.getGender()); // out: ♂

// Who I really am
me.setName('Batman');

// It changed!!
console.log(me.getName()); // out: Batman

Data Isolation

Although we can implement private variables with closures, what we want is to hide it as much as possible. The closure should be the only one to modify it state, there’s really no point in hiding it in a closure if you are going to reveal it anyway, an object would do the job instead.

This is the opposite of data encapsulation.

Let’s talk about a small definition to where closure applies easily

Idempotent Functions

Fancy words saying functions that always give the same output for the same input.

var twice = function (n) { return n * 2; }; // Math, very idempotent

// Weird function that adds whatever you put in last with the current
var addPrevious = function () {
    var previous = 0;

    return function (n) {
        oldPrevious = previous; // Store old value

        previous = n; // Mutate value

        return oldPrevious + n; // Do the math;
    }
}

var adder = addPrevious();

console.log(adder(5)); // out: 5   // oldPrevious = 0, newPrevious = 5
// Does not return the same value
console.log(adder(5)); // out: 10  // oldPrevious = 5, newPrevious = 10

var hiddenState = 0,
    decrement = function (n) {
        hiddenState += 1;
        return n - 1;
    };

// This has side effects but it is idempotent
console.log(decrement(4)); // out: 4 // hiddenState = 1
console.log(decrement(4)); // out: 4 // hiddenState = 2

Memoization

Just another short demonstration using closure. If a function is idempotent, you can cache the values. Caching for functions basically

// Memoization for one argument function
var memoize = function (f) {
    var cacheTable = {}; // Closure state, note that this hidden all throughout

    return function (n) { // Implemented for only one argument
        var cachedValue = get(n, cacheTable); // Get cached value

        if (cachedValue === undefined) { // If there is no cached value
            cachedValue = f.call(null, n); // Invoke the function
            set(n, cachedValue, cacheTable); // Store the value
        }

        return cachedValue;
    }
};

var encrypt = memoize(function (text) {
    var veryLongEncryptionAlgorithm = function _sha1Maybe(text) { /* ... */};

    return veryLongEncryptionAlgorithm(text);
});

Again, this is just to show that closures are supposed to hide state.

Starting With Functions

There is a nice feature or trick in JavaScript known as Immediately Invoked Function Expression or IIFE for short.

This just creating a function and invoking immediately.

var y = (function _iife() { // Just create a function
    return 1; // Why do this?
}()); // ... and wrap it with an open close parenthesis

var z = 1; // Why not just do this instead?

This is cute, but what is is good for? Since it is a function, it has closure; so anything you put inside it, remains inside.

Creating A Namespace

When creating scripts for JavaScript, it’s good to wrap the whole script as an IIFE to prevent and variable leaks since the default scope of variables is global.

(function _importMyCustomScript() {
    var myScriptVar = 1;

    // Assume the global namespace for my app is XYZ
    XYZ.myFunction = function () { return myScriptVar; };
}());

This goes hand in hand with creating a global namespace if you are working with the browser but we’re not really going to dwell into that.

Creating A Module

You can also create a module using IIFE with this pattern.

// Using IIFE to make modules
var FP = (function () {
    var hiddenVarInModule = 1;

    // Object.create allows us to create truly empty object
    var Module = Object.create(null); // or {} is enough if you don't care

    // Object.freeze makes an object readonly
    return Object.freeze(Module); // or Module if you don't care
    // Return the module
}());

Starting An Idea

Not the best use, but when you are trying to sketch a function and can’t decide if it can be refactored. Starting with IIFE can get you started.

var originalFunction = function () {
    // Blah blah blah

    // New feature, need a better name for this function
    (function _newFeature() { // If this is used again, it is easier to refactor
        // Everything I do is within this bubble

        var x = 1,
            y= 'a';

        // Do more stuff
    }())


    // Blah blah blah
};

I usually sketch the prototype within an IIFE, and keep it there to give it a good indication of what it does. Then if it used again, I just turn into an legit function and refactor.

Stateful Talk

Hiding state.

This is what closures should ultimately do. But what if you had to? Here are some examples.

Objects As Stateful Value

JavaScript has blessed syntax for object creation: easy and flexible to use.

var myObject = {
    myText: '',
    myValue: null,
    mySubObject: {
        isEmpty: true
    },
};

// It's actuall okay to mutate
// NOTE: A comment to say that it mutates
var newObject = set('myText', 'xyz', myObject);

console.log(myObject.myText); // out: 'xyz'
// but
console.log(newObject === myObject); // out: true

I put an object in, I get an object out. I don’t care if you mutated it, but be very mindful or explicit about this. Comments are your friends. Using objects as a data format is a solid way to go about it.

One of your friends too in this field is known as Immutability which might be a different topic.

State As A Value

What if given a big list of numbers, compute the average; what if you could loop through it once? How would you do it?

var bigDoop = [1, 2, 3, /* ... */, 10000000]; // Just a very big set

// What appears to be more cumbersome
var computeAverage = function (numbers) {
    var getSum = curry(get)(0),
        getCount = curry(get)(1);

    var totals = numbers.reduce(function (prev, number) {
        var currentSum = getSum(prev),
            currentCount = getCount(prev);

        return [currentSum + number, currentCount + 1];
    }, [0, 0]); // Setting the initial state

    var sum = get(0, totals),
        count = get(1, totals);

    return sum / count;
};

console.log(computeAverage(bigDoop)); // out: More numbers than Iron Man

Notice the use of a lists to pass in state, the count and the sum. If you’re in a pipeline, it is much better to make the state explicit as a value for all to see and inspect.

State As An Argument

This is not really practical but just to get your attention. Let’s implement a fancy recursive factorial implementation.

// Avoid doing this, this is not helpful
var factorial = function (n) {
    var factorialHelper = function _recurse(n, value) {
        if (n <= 0) { // If done, return the value
            return value;
        } else { // Else, do it again with the new state
            return _recurse(n - 1, value * n); // This is unhealthy to pass state
        }
    };

    return factorialHelper(n, 1); // Call with initial state
};

var factorialWhile = function (n) {
    var value = 1;

    while (n > 0) {
        value *= n;
        n-= 1;
    }

    return value;
}

If JavaScript was tail optimized, we would really do more of this but it scares me to do it. But this is just to show the weird way to pass in state.

Managing State Is Hard

In reality, hiding state is hard.

Being explicit about state almost translates to more code; this is what can put you off to declare that global variable or just hack the state variables.

I suggest paying the explicit code than someone paying for it implicitly.

Know Thy Closure

Despite all that rant about state, if JavaScript didn’t have closure, I wouldn’t know what to do about my work and there really wouldn’t be a functional paradigm for it.

Imagine if you could access all the variables inside a function?

Quick Review

Have I made my point?

  • Closures are underrated in managing state
  • State makes code more complex, hide if you must
  • Objects and lists make excellent function data interchange

Epilogue: JavaScript Is Functional

End of the line.

JavaScript Is Awesome

JavaScript is really cool for me because of the following.

  • First class functions
  • Closures
  • Function scoped

That’s really it.

(I could say the same thing about Python which holds a special place in my heart.)

The Power Of Functions In JavaScript

If you forgot what I said, here it is.

  • Use map, filter, and reduce
  • Learn compose and curry
  • Think input and output, processes not details
  • Avoid for loops and ifs
  • Hide implementation details
  • Hide state as much as possible
  • Have fun

What I Didn’t Say

Compare JavaScript with Haskell if you want to see the light

  • Types
  • Monads
  • Functors
  • Patterns
  • So much

Future Of Functional Programming

I am not an Oracle but…

  • Functional Reactive Programming
  • React & React Native
  • Clojure / ClojureScript
  • RxJs
  • Elm
  • Java 8: Lambdas

Really, it’s just a good time to learn a new paradigm to widen your perspective.

Lastly

No matter what I say or what paradigm is out there. Good code is something you work for. There is really no silver bullet.

Don’t be a zealot. OOP and FP have their places in design and coding. Use your judgment which works for the correct situation.

But really in JavaScript, I find FP to be really easy to work with than its Prototypical nature.

Now GTFO

Thank you for letting me waste your time. I hope you learned something or even just the idea.

References

Books

Libraries

  • lodash - a good functional library
  • jquery - not obvious but it really is a monad
  • rxjs - functional reactive programming library

Languages

  • haskell - the language drug to functional programming
  • clojure - the functional lisp since Scheme
  • clojurescript - the lisp for javascript
  • elm - the functional javascript

About

Manila, Javascript 06

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published