functional programming in javascript

24
FUNCTIONAL PROGRAMMING IN JAVASCRIPT Or, “How lambdas can change your life”

Upload: joseph-smith

Post on 08-Aug-2015

122 views

Category:

Technology


2 download

TRANSCRIPT

FUNCTIONAL PROGRAMMING IN JAVASCRIPTOr, “How lambdas can change your life”

Some basic questions

What is functional programming and how does it differ from imperative programming?

What is JavaScript? What is functional programming in

JavaScript, and how can it help me?

Two Models of Computation

Lambda calculus: Emil Post, 1936 Turing Machine: Alan Turing, 1936-1937 Proved equivalent in computational

power by Turing in 1937

Turing Machine

Infinite tape Head moves over tape, can read symbol,

change symbol, go left, or go right Modifying state in a particular order,

according to instructions “Mechanized symbol evaluation based

on assignment and time ordered evaluation”

Imperative Languages

Assignment sequences Same name can be associated with

several values Fixed evaluation orders New values can be associated with the

same name through command repetition

A classic imperative loop

function fib(n) { var a = 0, b = 1, f = 1; for (var i = 2; i <= n; i++) { f = a + b; a = b; b = f; } return f;};

Order is important

var x = 1, y = 2, buffer;buffer = x;x = y;y = buffer;// x = 2, y = 1

var x = 1, y = 2, buffer;x = y;buffer = x;y = buffer;// x = 2, y = 2

Lambda Calculus

Roots in mathematical logic and proof theory

Turing machines = Kleene’s recursive function theory = lambda calculus = generalised von Neumann machines

Attempt to describe computation in terms of computable functions

Functional Languages

Based on structured function calls: a(b(c(3)))

So what? You can nest functional calls in C! But in pure functional languages, this is the

only way to transform values: a name is only ever associated with one value

Functions as first-class citizens No assignment = no side effects Can be executed in different orders but give

the same result

Recursion instead of looping

function fib(n) {if (n <= 2) {

return 1;}return fib(n-1) + fib(n-2);

}

Functions as first-class citizens

var arr = [42, function() { return 42; }];

var obj = {key: 42, func: function() { return 42; }}

var x = function() { return 42; };

var y = function() { return function() { return 42} };

42 + (function() { return 42; })()

//=> 84

function weirdAdd(n, f) { return n + f() }

weirdAdd(42, function() { return 42 });

//=> 84

JavaScript

Developed by Brendan Eich at Mozilla Scheme in the browser “Lisp in C’s clothing” Supports many programming paradigms:

Classical object-oriented Prototype-based Imperative Functional

Functional JavaScript

Functions as first-class citizens Anonymous functions Native methods:

.map() .reduce() .forEach()

Event-based programming (DOM API, XmlHttpRequest)

Closures

.map()

var numbers = [1, 4, 9];var roots = numbers.map(Math.sqrt);console.log(roots);var doubledRoots = roots.map( function(n) { return n * 2; });console.log(doubledRoots);

.map() imperative alternativevar numbers = [1, 4, 9];var roots = [];

for (var i=0; i<numbers.length; i++) { roots.push(Math.sqrt(numbers[i]));}

console.log(roots);

var doubledRoots = [];for (var i=0; i<roots.length; i++) { doubledRoots.push(roots[i] * 2);}

console.log(doubledRoots);

.reduce()

[0, 1, 2, 3, 4].reduce(

function(previousValue, currentValue, index, array) {

return previousValue + currentValue;

}

);

Event callbacks

document.addEventListener('click', function() {

console.log('You clicked somewhere!');

});

var clicked = function() {

console.log('You clicked somewhere!’)

};

document.addEventListener('click', clicked);

Closures

function makeFunc() { var name = "Mozilla"; function displayName() { console.log(name); } return displayName;}

var myFunc = makeFunc();myFunc();

Self-executing functions

var counter = (function(){ var n = 0; return function() { console.log('Times run: ‘+(++n)); }})();

99 Bottles of Beer: imperative

var lyrics = [];

for (var bottles = 99; bottles > 0; bottles--) { lyrics.push(bottles + ' bottles of beer on the wall'); lyrics.push(bottles + ' bottles of beer'); lyrics.push('Take on down, pass it around');

if (bottles > 1) { lyrics.push((bottles - 1) + ' bottles of beer on the wall.'); } else { lyrics.push('No more bottles of beer on the wall!'); }}

99 bottles of beer: functionalfunction lyricSegment(n) { return _.chain([]) .push(n + ' bottles of beer on the wall') .push(n + ' bottles of beer') .push('Take one down, pass it around') .tap(function(lyrics) { if (n > 1) { lyrics.push((n - 1) + ' bottles of beer on the wall'); } else { lyrics.push('No more bottles of beer on the wall'); } }) .value();}

99 bottles of beer: functional

function song(start, end, lyricGen) { return _.reduce(_.range(start, end, -1), function(acc, n) { return acc.concat(lyricGen(n)); }, []);}

10 green bottles!

function greenBottles(n) { return _.chain([]) .push(n + ' green bottles sitting on the wall') .push(n + ' green bottles hanging on the wall') .push('And if 1 green bottle should accidentally fall') .tap(function(lyrics) { if (n > 1) { lyrics.push('There\'ll be '+ (n - 1) + ' green bottles hanging on the wall'); } else { lyrics.push('There\'ll be no more bottles hanging on the wall'); } }) .value();}

Conclusions

JavaScript brought functional programming into the mainstream

Its functional features are indispensable for event-driven programming and for general elegance

Just a glimpse of what “pure” functional languages provide (immutability, purity, algebraic data types)

But enough to make JavaScript a powerful and flexible language

Explore underscore.js!