shape-of-fun



shape-of-fun

3 2


shape-of-fun

Slides for the talk "The Shape of Functional Programming"

On Github funjs / shape-of-fun

The Shape of Functional Programming

@fogus

@fogus

var array = [0,1,2,3,4,5];

var transformed = [];

for (var i = 0; i < array.length; i++) {
  transformed.push(array[i] + 100);
}

transformed;
	    var array = [0,1,2,3,4,5];
	  
// Underscore

_.map(array, function(n) {
  return n + 100;
});


// Lemonad

L.map(L.add(100), array);
	    var array = [0,1,2,3,4,5];
	  
var keepers = [];

for (var i = 0; i < array.length; i++) {
  if (array[i] % 2 === 0) {
    keepers.push(array[i]);
  }
}

keepers;
	    var array = [0,1,2,3,4,5];
	  
// Underscore

_.filter(array, function(n) {
  if (n % 2 === 0) {
    return true;
  }
  else {
    return false;
  }
});

// Lemonad

L.filter(L.isEven, array);
	    var array = [0,1,2,3,4,5];
	  
var sum = 0;

for (var i = 0; i < array.length; i++) {
  sum += array[i];
}

sum;
	    var array = [0,1,2,3,4,5];
	  
// Underscore

_.reduce(array, function(acc, n) {
  return acc + n;
}, 0);


// Lemonad

L.reduce(L.uncurry(L.add), 0, array);

Fun.js at a glance

  • Simple data
  • Small functions
  • Larger abstractions from simple data
  • Larger abstractions from composing small functions
  • OO to supplement
  • No dogma

simple data

42

small functions

function nth(array, index) {
  return array[index];
}


nth(['a', 'b', 'c'], 1);

abstractions, composed from primitives

var table = [

 {id:   '555-55-5555',
  name: 'Moe',
  age:  45},

 {id:   '777-77-7777',
  name: 'Curly',
  age:  47}

 ];
	   var table = [

	    {id:   '555-55-5555',
	     name: 'Moe',
	     age:  45},

	    {id:   '777-77-7777',
	     name: 'Curly',
	     age:  47}

	    ];
          
function cell(table, col, row){
  return table[row][col];
}


cell(table, "name", 0);


cell(table, "age", 0);
Codd.js
var itunes = [
    {'artist' : 'Sun Ra',
     'genre'  : 'Jazz',
     'plays'  : 379},

    {'artist' : 'Om',
     'genre'  : 'Doom',
     'plays'  : 22},

    {'artist' : 'Can',
     'genre'  : 'Prog',
     'plays'  : 190},

    {'artist' : 'Popol Vuh',
     'genre'  : 'Prog',
     'plays'  : 285}
];
	    var itunes = [
	        {'artist' : 'Sun Ra',
	         'genre'  : 'Jazz',
	         'plays'  : 379},

	        {'artist' : 'Om',
	         'genre'  : 'Doom',
	         'plays'  : 22},

	        {'artist' : 'Can',
	         'genre'  : 'Prog',
	         'plays'  : 190},

	        {'artist' : 'Popol Vuh',
	         'genre'  : 'Prog',
	         'plays'  : 285}
	    ];
          
function cell(col, row, table) {
  var entry = table[row];
  return entry && entry[col];
}

cell('artist', 1, itunes);
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
function cell(col, row, table) {
  var entry = table[row];
  return entry && entry[col];
}


function getArtists(library) {
  var ret = [];

  for (var i = 0; i < library.length; i++) {
    ret.push(cell('artist', i, library));
  }

  return ret;
}

getArtists(itunes);

Codd.project

	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
Codd.project(itunes, ['artist']);
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
Codd.project(itunes, ['artist', 'plays']);
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
Codd.project(itunes, ['artist', 'plays']);

/***
 SELECT artist,plays FROM itunes;
 ***/
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.project(itunes, ['artist', 'plays']), 'plays');
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.project(itunes, ['artist', 'plays']), 'plays');

/***
 SELECT artist,plays FROM itunes
 ORDER BY plays;
 ***/

Codd.rename

	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.rename(Codd.project(itunes, ['artist', 'plays']), {artist: 'band'}), 'plays');
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.rename(Codd.project(itunes, ['artist', 'plays']), {artist: 'band'}), 'plays');

/***
 SELECT artist AS "band", plays
 FROM itunes
 ORDER BY plays;
 ***/

Codd.restrict

	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.restrict(Codd.rename(Codd.project(itunes, ['artist', 'plays']), {artist: 'band'}), function(cell) { return cell.plays > 200 }), 'plays');
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.sortBy(Codd.restrict(Codd.rename(Codd.project(itunes, ['artist', 'plays']), {artist: 'band'}), function(cell) { return cell.plays > 200 }), 'plays');

/***
 SELECT artist AS "band", plays
 FROM itunes
 WHERE plays > 200
 ORDER BY plays;
 ***/

Abstractions from functions: composition and pipelines

	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.size(Codd.col(itunes, 'artist'));
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.compose(_.size, Codd.col)(itunes, 'artist');
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
_.compose(_.size, Codd.col)(itunes, 'artist');
          _.size( Codd.col( itunes, 'artist'));
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
L.pipeline(itunes, Codd.col('artist'), _.size);
	    var itunes = [{'artist' : 'Sun Ra', 'genre'  : 'Jazz', 'plays'  : 379}, {'artist' : 'Om', 'genre'  : 'Doom', 'plays'  : 22}, {'artist' : 'Can', 'genre'  : 'Prog', 'plays'  : 190}, {'artist' : 'Popol Vuh', 'genre'  : 'Prog', 'plays'  : 285}];
          
var orderBy = L.rcurry2(_.sortBy);

L.pipeline(itunes,
           Codd.RQL.select(['artist', 'plays']),
           Codd.RQL.as({artist: 'band'}),
           Codd.RQL.where(Codd.RQL.field('plays', L.gt(200))),
           orderBy('plays'));

/***
 SELECT artist AS "band", plays
 FROM itunes
 WHERE plays > 200
 ORDER BY plays;
 ***/