Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Functional Programming in Javascript

with Ramda.js

          
        var R = require('ramda');
        

Functions are Values

A language where functions are values has first class functions

Functions can be stored in variables and passed as arguments like any other value

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

Pure Functions

the best kind

A pure function has only inputs and output

A pure function mutates no state

          
    var someArray = [1, 2, 3];
    someArray.push(4);
        

This mutates someArray.

          
  var purePush = function(item, array) {
    var newArray = array.slice();
    newArray.push(item);
    return newArray;
  };

  purePush(4, someArray);
        

This returns a new array and leaves someArray alone.

Higher Order Functions

A higher order function takes a function as an argument

          
        > R.inc(1);
        2

        > R.map(R.inc, [1, 2, 3]);
        [2, 3, 4]
        

Currying

not the food

When not given enough arguments:

          
        > var incEach = R.map(R.inc);

        > incEach([1, 2, 3]);
        [2, 3, 4]
        

Argument Order

Initial arguments to a function are like configuration

The last argument is usually the data to operate on

This makes it easy to create specialized functions with currying

          
  var getNamed = R.filter(R.has("name"));

  > getNamed([
    {id: 0, name: "foo"},
    {id: 1},
    {id: 2, name: "bar"}
  ]);
  [{id: 0, name: "foo"},
   {id: 2, name: "bar"}]
        
          
  var firstNamed = R.find(R.has("name"));

  > firstNamed([
    {id: 0, name: "foo"},
    {id: 1},
    {id: 2, name: "bar"}
  ]);
  {id: 0, name: "foo"}
        
          
  var isEven = function(x) {
    return x % 2 === 0;
  };

  var evensOnly = R.filter(isEven);

  > evensOnly([1, 2, 3, 4, 5]);
  [2, 4]
        
          
  var duplicate = function(x) {
    return [x, x];
  };

  var duplicateEach = R.chain(duplicate);

  > duplicateEach([1, 2, 3]);
  [1, 1, 2, 2, 3, 3]
        

Thus Ends Section One

Let's take a quick break now

Function Composition

putting it all together

Mathematical Functions

A function of one argument f(x) and another function of one argument g(x) can be composed together to make the function f(g(x))

          
  > duplicateEach([1, 2, 3]);
  [1, 1, 2, 2, 3, 3]

  > evensOnly([1, 2, 3, 4, 5]);
  [2, 4]

  var duplicateEvens = R.compose(
    duplicateEach,
    evensOnly
  );

  > duplicateEvens([1, 2, 3, 4, 5]);
  [2, 2, 4, 4]
        

Exercises!

not the sweaty kind

Let's tackle some exercises and apply these concepts

Suppose we're working with a JSON API that provides a giant catalog of users.

Each user has an id, a name, and an age

          
  {
    users: [
      {id: 3, name: "Thad", age: 36},
      {id: 5, name: "Lucian", age: 23},
      {id: 2, name: "Justine", age: 29},
      {id: 4, name: "Katie", age: 26},
      {id: 0, name: "Jerold", age: 52},
      {id: 1, name: "Nona", age: 33}
    ]
  }
        

You can find this catalog in the "exercises" folder of the class GitHub repository.

Sorting by ID

npm run-script ex1

It would be useful to see a list of users sorted by ID

Ramda provides a sortBy function to make this easier.

Note: it's a higher order function!

          
  var sortCatalogUsersById = R.compose(
    R.sortBy(R.prop("id")),
    R.prop("users")
  );
        

Users With an Even Age

npm run-script ex2

Now for some filtering

Let's say we want only the users in the catalog with an even age

Tip - if you've got isEven, check out Ramda's propSatisfies.

          
  var isEven = function(x) {
    return x % 2 === 0
  };

  var hasEvenAge = R.propSatisfies(
    isEven,
    "age"
  );

  var getUsersWithEvenAge = R.compose(
    R.filter(hasEvenAge),
    R.prop("users")
  );
        

Names of the Three Youngest Users

npm run-script ex3

Instead of sorting by ID, let's sort by age

Additionally, let's get the 3 youngest users instead of all of them

As a final twist - let's only get their names, not the whole user objects

          
  var getNamesOfThreeYoungestUsers =
    R.compose(
      R.map(R.prop("name")),
      R.take(3),
      R.sortBy(R.prop("age")),
      R.prop("users")
  );
        

Users in their Thirties

npm run-script ex4

Now a somewhat more complex query - let's get all the users with age 30-39

Ramda provides R.lt, and R.gt for comparing, but their argument order makes things tricky

Maybe try R.flip or R.__

          
  var isInThirties = R.both(
    R.gte(R.__, 30),
    R.lt(R.__, 40)
  );

  var userIsInThirties = R.propSatisfies(
    isInThirties,
    "age"
  );

  var getUsersInTheirThirties = R.compose(
    R.filter(userIsInThirties),
    R.prop("users")
  );
        

Congratulations!

you survived!

Now you know the main techniques of functional programming in Javascript