Functional Programming

    http://output.jsbin.com/yoyip

    Separate mutation from calculation.

    Functions should be so specific that they can be easily unit tested without having to do complex mocks.

    Pure Functions

    Functions that don’t change anything, they just compute and return a result.
    Characteristics:

    • easy to unit test
    • portable: can be used on client and on server
    • memoizable: it caches the results so its faster the next time they run the function with the same input.
    • parellalizable: you can run them in parallel with other functions since they won’t mutate anything.
    • The dependencies and inputs must be pure too, otherwise it will pollute the function. (eg. injecting a console through the arguments to be able to do console.log).

    Separate Functions from Rules

    A function is a single-valued collection of pairs. For each input (domain) case there will be only one outcome (range) and will always be the same.

    e.g.

    Arity - The ability to accept n amount of arguments.

    • Nullary
    • Binary
    • Ternary
    • n-ary

    Function to curry

    1. return function() {
    2. if(fn.length > arguments.length) {
    3. var slice = Array.prototype.slice;
    4. var args = slice.apply(arguments);
    5. return function() {
    6. return fn.apply(
    7. null, args.concat(slice.apply(arguments))
    8. );
    9. }
    10. }
    11. return fn.apply(null, arguments);
    12. };
    13. }

    Curry example

    1. // Example without currying
    2. let dragons = [
    3. {name: 'fluffykins', element: 'lightning' },
    4. {name: 'noomi', element: 'lightning' },
    5. {name: 'karo', element: 'timewarp' },
    6. {name: 'doomer', element: 'fire' },
    7. ]
    8. let hasElement = (element, obj) => obj.element === element;
    9. let lightningDragons = dragons.filter(x => hasElement('lightning', x))
    10. console.log(lightningDragons)
    11. // [ {name: 'fluffykins', element: 'lightning' }, {name: 'noomi', element: 'lightning' },]
    12. // make it curryiable with lodash
    13. hasElement = _.curry((element, obj) => obj.element === element);
    14. lightningDragons = dragons.filter(hasElement('lightning'));
    15. console.log(lightningDragons)

    An example without lodash

    Composition

    Is like using unix pipe

    Point free

    aka Argument free

    The real definition of MAP

    Map is not limited to iteratable objects. Map is whenever a method gets applied inside the object.

    If it has a map function, it is a functor

    Maybe Functor

    1. var _Maybe.prototype.map = function(f) {
    2. return this.val ? Maybe(f(this.val)) : Maybe(null);
    3. };
    4. // => Maybe(null)
    5. // eg
    6. var firstMatch = compose(first, match(/cat/g));
    7. firstMatch('dogsup); // breaks
    8. // instead do
    9. var firstMatch = compoase(map(first), Maybe, match(/cat/g));
    10. firstMatch('dogsup); // => Maybe(null)

    Identity functor

    Theories

    Category Laws

    You need an identity function

    High Order Functions

    Are functions that accept other functions as arguments.

    Eg. [].filter()

    Composition

    When you pass another function to the high order function you are composing. Making a more complex function out of two simple functions. This is easier to reason about and to debug than having everything in a single function.

    Reduce is awesome

    Array.reduce is not only to get the sum of an array of numbers. It can also be used to compose an object.

    eg. set an object of customers coming from an array of lines

    1. const output = file
    2. .split('\n')
    3. .trim()
    4. .map(x => x.split('\t'))
    5. .reduce((customers, line) => {
    6. customers[line[0]] = customers[line[0]] || [];
    7. customers[line[0]].push({price: line[1]})
    8. return customers;
    9. }, {});

    Reference

    • Hardcore Functional Programming - Frontend Masters