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;
	     ***/