Hi.

                          make(your)
                            (life(
                              better(
                                with {
                                  function(al) {
                                    programming();
                                  }})));

What's it gonna be about

  • Functional aspects of JS
  • A different JS programming approach
  • Higher-order functions
  • Recipes, recipes, recipes...
  • Wrap-up

Questions?

Interrupt me anytime to ask them. :)

I lied to you.

The title should be make your life DIFFERENT... but that doesn't sell ;)

The Wikipedia definition

JavaScript is a prototype-based scripting language with dynamic typing and has first-class functions.

What you should see

JavaScript blablabla cookies kittens unicorns dynamic typing wolfenstein patrick swayze first-class functions.

Having first-class functions means we can throw them around as we please.

And dynamic typing means that the interpreter won't complain as to what they take in or return.

What does that add up to?

JS will do what we want and how we want it to- without asking too much questions.

Let's start with an obligatory trivial, contrived example. :)
// some `happiness` and `GUI` stuff accessible globally
function handleHappiness(howHappyAmI) {
    switch (howHappyAmI) {
        case "very happy":
            happiness += 2;
            GUI.showAHappyFace();
            break;
        case "happy":
            happiness += 1;
            GUI.showAHappyFace();
            break;
        case "sad":
            happiness -= 2;
            GUI.showASadFace();
            break;
    }
}

A switch is not so bad- it works, right? But we all can do better...

right?

How about this...

var happinessStateEffects = {
    "very happy": function (happiness, GUI) {
        GUI.showAHappyFace();
        return happiness + 2;
    },
    "happy": function (happiness, GUI) {
        GUI.showAHappyFace();
        return happiness + 1;
    },
    "sad": function (happiness, GUI) {
        GUI.showASadFace();
        return happiness - 2;
    }
};

function handleHappiness(howHappyAmI) {
    return happinessStateEffects[howHappyAmI](happiness, GUI);
}

Ok, how about returning a function or passing it as a param?

Let's also split this functionality in two to reflect the responsibilities.

Firstly, what can be done with the happiness:

function HappinessStateEffectsFactory() { 
    var happinessStateEffects = {
        "very happy": function (happiness, GUI) {
            GUI.showAHappyFace();
            return happiness + 2;
        },
        "happy": function (happiness, GUI) {
            GUI.showAHappyFace();
            return happiness + 1;
        },
        "sad": function (happiness, GUI) {
            GUI.showASadFace();
            return happiness - 2;
        }
    };

    this.getHappinessStateEffect = function(howHappyAmI) {
        return happinessStateEffects[howHappyAmI];
    };
}

And then how should it be arranged to be done:

(function(happinessFactory, happiness, GUI){
    function handleHappiness(howHappyAmI) {
        return happinessFactory
            .getHappinessStateEffect
                (howHappyAmI)
                (happiness, GUI);
    }

    window
    .useABetterModuleSolution
    .handleHappiness = handleHappiness;
}(theHappinessFactory, someHappinessProvider, someGuiModule));

The benefits of this approach

  • A framework of configurable behaviors, representing the 'domain'
  • A set of 'plumbing' functions used to orchestrate the configurable behaviors
  • A clear division between the two

The benefits of this approach

  • This scales. In an ideal case the two aspects of behavior are orthogonal.
  • It reads more easily. Noobs like me can see almost right off the bat what's really going on if they step through the code.
  • It is much easier to debug:
    • the characteristics of a bug tend to strongly point to its origin (is the domain or the plumbing screwed up?)
    • treating values as immutable makes your head spin less when setting watches

FP influences in this approach

  • Make effort to explicitly separate state from behavior (and even behavior from behavior !) like a maniac
  • Leave the frickin values alone! (don't mutate)
  • Extract every little thing you do into a function and name it- let it describe what it accomplishes
    (chapeau bas to Uncle Bob and Martin Odersky here!)

A word about mutating state

I'm not going to elaborate on that topic a lot - but it's implied as a rule in this presentation that we should avoid mutating state unless it's really necessary

A word about mutating state

How your code should be like...

How your code should be like

A word about mutating state

How your code is like when you mutate too much:

How your code is like when you mutate too much

The rest of this talk is going to be pure JS meat.

Please don't forget about asking me questions! ;)

Higher-order functions

A function returning a function. Simple as that.

function iIncreaseValues(howMuchToIncreaseIt){
    return function thatIsHowIRoll(whatToIncrease) {
        return whatToIncrease + howMuchToIncreaseIt;
    };
}

Higher-order functions

Usage

var increaseDatByTwoPlease = iIncreaseValues(2);
var hereYouGoBoss = increaseDatByTwoPlease(4); // 6!!! WOW!
iIncreaseValues(2)(4); // also 6!!!

Higher-order functions

In this case, the simplest of tools open the biggest world of opportunities.

Higher-order toolset embedded in JavaScript

  • Array.prototype.forEach
  • Array.prototype.map
  • Array.prototype.filter
  • Array.prototype.reduce
  • Array.prototype.some (homework ;))

These should practically be the lowest level you get with higher order functions.

Array.prototype.forEach

Remember the for loop?

var interestingData = [/*...*/];
for(var i = 0, l = interestingData.length; i < l; i += 1){
    var x1 = Math.sqrt(Math.exp(data[i]));
    var x2 = Math.pow(Math.atan(data[i]), data[i] % 3);
    printer.print(Math.pow(x1,x2));
}

Array.prototype.forEach

How about...

var interestingData = /*...*/;
function compute(baseValue) {
    var x1 = Math.sqrt(Math.exp(baseValue));
    var x2 = Math.pow(Math.atan(baseValue), baseValue % 3);
    return Math.pow(x1, x2);
}

interestingData.forEach(function(value){ printer.print(compute(value)); });

Not really mind-blowind, I know.

But it can be taken further:

function printComputationResult(value) { printer.print(compute(value)); }

And what this allows:

interestingData.forEach(printComputationResult); // I like this!

Now, to me, that's expressive. I think all top-level code should be like that.

Array.prototype.map

It's basically a forEach, but it returns the values.

var computedResults = interestingData.map(function(value) {
    return compute(value);
});

function print(result) { printer.print(result); }
computedResults.forEach(print);

And that leads up to...

interestingData.map(compute).forEach(print);

Array.prototype.filter

It maps the elements of an array to boolean values through the given predicate.

If the result is truthy, the element gets included in the result.

var freeDays = ["sat","sun"];
function isAWorkingDay(day) { return freeDays.indexOf(day) === -1; }

["mon","tue","wed","thu","fri","sat","su"].filter(isAWorkingDay);
// ["mon","tue","wed","thu","fri"]

reduce

Applies a function to an accumulator and each value of the array.

The return value is being taken as the accumulator for the next iteration.

reduce

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

function sum(arr) { return arr.reduce(add); }
sum([1,3,5]); // 9

function sumVariadic() { return sum([].slice.call(arguments)); }
sumVariadic(1,3,5); // 9
                        

Walking through the reduction process...

1) add(0, 1) { return 0 + 1; }
2) add(1, 3) { return 1 + 3; }
3) add(4, 5) { return 4 + 5; }

reduce is the mother of the higher-order toolset functions. You can do pretty much everything presented before with it- and more.

These are the most basic blocks you can get.

Let's get on to more interesting stuff.

maybe

Remedies the need for having null checks everywhere.

function maybe (fn) {
  return function () {
    var i;

    if (arguments.length === 0) return;
    else {
      for (i = 0; i < arguments.length; ++i) {
        if (arguments[i] == null || typeof(arguments[i]) === "undefined") return;
      }
      return fn.apply(this, arguments);
    };
  }
}

maybe

Makes your code more idiomatic, removing technical boilerplate.

function computeStupidly(a,b,c) {
    if(a!== null && typeof(a) !== "undefined" && 
       b!== null && typeof(b) !== "undefined" &&
       c!== null && typeof(c) !== "undefined") {
        console.log(a*Math.pow(b,c));
    }
}

// it's much more concise with maybe
var computeWisely = maybe(function(a,b,c){
    console.log(a*Math.pow(b,c));
});

maybe

Note that this version of maybe will not preserve the function's arity!

var computeWisely = maybe(function(a,b,c){
    console.log(a*Math.pow(b,c));
});

computeWisely(1,null,5); // undefined
computeWisely(1,5); // NaN :(

To remedy that, you'd have to use toString on the function and extract the number of arguments from its definition.

once

Makes sure that a function is executed only once.

function once(fn) {
    var executed = false;
    return function() {
        return executed ? void 0 : ((executed = true), fn.apply(this, arguments))
    };
}

once

An example - quite straightforward

function magicComputator(value) {
    return Math.pow(Math.exp(3/value), value * Math.sqrt(3));
}

var doNotDateToComputeTwice = once(magicComputator);

doNotDareToComputeTwice(3); // 180.57612295783412
doNotDareToComputeTwice(3); // undefined

once

There is a pitfall here- you have to use a named function.

once(function() { return "Uh"; }); // Uh.
once(function() { return "Uh"; }); // Uh.

once

The recipe can be easily modified to alleviate some of that pain by using the Function.name property.

Unfortunately, this property is not even on a JS standards track, so it's not safe to use it.

fluent

Make instance methods chainable.

function fluent (methodBody) {
      return function () {
        methodBody.apply(this, arguments);
        return this;
      }
    }

fluent

Obvious usage - relieve yourself of having to write return this; all the time.

function Pigeon() {}
Pigeon.prototype = {
    defecateOnPeople: fluent(function(){/* do something without returning `this` */}),
    defecateSomewhereElse: fluent(function(){/* do something without returning `this` */})
};

new Pigeon()
    .defecateOnPeople()
    .defecateOnPeople()
    .defecateOnPeople(); // they don't use the other method.

mapWith

Transforms any function into a mapping, working on an array.

function mapWith (fn) {
  return function (list) {
    return Array.prototype.map.call(list, function (something) {
      return fn.call(this, something);
    });
  };
};

mapWith

Remember the Array.prototype.map example?

function compute(baseValue) {
    var x1 = Math.sqrt(Math.exp(baseValue));
    var x2 = Math.pow(Math.atan(baseValue), baseValue % 3);
    return Math.pow(x1, x2);
}

function print(value) { printer.print(value); }
interestingData.map(compute).forEach(print);

It could be written even more concisely now.

var computeAll = mapWith(compute);
computeAll(interestingData).forEach(print);

In practice, for me that is probably the most used 'toolset' function. It's insanely helpful.

These are just a few helpers. There is a lot more.

To get a better idea- I recommend @raganwald's excellent Javascript Allongé book.

He formalized thoughts from the book in the allong.es library.

Underscore/lodash also implement similar ideas, though with a little different approach and naming.

Speaking of Underscore...

Function composition

Underscore provides a _.compose method.

Function composition is another one of the simple concepts giving great power.

To compose functions means to connect them in a cascading chain, called in a specific order.

function a() { /*...*/ }
function b() { /*...*/ }

_.compose(a,b) === function () { return a(b()); };

Right to Left.

function composition

I talked about explicitly separating the two behavior types earlier.

Function composition provides an abstraction which allows explicitly stating how should certain behaviors be orchestrated.

I see it as the final piece to make the aforementioned approach feasible and practical.

With composition, every step of the process can be made idiomatic.

state + behavior + orchestration

Small demo.

wrap-up

Summary

  • Maintain explicit boundaries between different types of behavior.
  • Don't mutate state unless you really have to.
  • Name everything- good abstraction is king.
  • Top-level code should be idiomatic - point-free (pointles / tacit) programming

wrap-up

a list of things to look up :)

  1. JavaScript Allongé - READ THIS!!!
  2. Effective JavaScript by David Herman
  3. http://functionaltalks.org/, especially this talk for starters
  4. Functional programming principles in Scala - an awesome course by an awesome dude
  5. A follow-up course by the same man
  6. Uncle Bob rocking my world as always

about me:

  1. Github
  2. LinkedIn
  3. Facebook
  4. Msg me if you want to talk or have more questions! :)