learn you a functional javascript for great good

Post on 06-May-2015

902 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

We have been told by just about everyone that we should learning functional programming, let this session be your introduction using a language you already know JavaScript. Yep, JavaScript. No endless amounts of parentheses. No monadic arrows. Just good old JavaScript. We'll look take a look at the functional JavaScript landscape see how to use: Currying Combinators Multimethods We'll be using Underscore.js, allong.es, and bilby.js to help us.

TRANSCRIPT

Learn You a Functional JavaScript for Great Good!Mike Harris

Functions!

Closures!

Currying!

Combinators!

Multimethods

Frameworks

> require("underscore");!{ [Function]! _: [Circular],! VERSION: '1.6.0',! …! map: [Function],! …! filter: [Function],! reject: [Function],!…! compose: [Function],! after: [Function],!…!}

> require("allong.es");!{ es: ! {!…! flip: [Function: unary],!…! curry: [Function: unary],! map: [Function: binary],! mapWith: [Function: binary],! mapArgumentsWith: [Function: binary],! filter: [Function: binary],! filterWith: [Function: binary],!…! allong: [Circular] }

> require("bilby");!{!…! curry: [Function: curry],! flip: [Function: flip],! identity: [Function: identity],! constant: [Function: constant],! compose: [Function: compose],!…! lens: [Function: lens],! isLens: [Function],! objectLens: [Function: objectLens],!…!}

Functions

nothing

function nothing(){};!!

nothing();!undefined

five

function five(){return 5;};!!

five();!5

makeFive

function makeFive(){! return function(){return 5;}!};!!makeFive();![Function]!var five = makeFive();!five();!5

fAdd

function five(){return 5;};!!

function fAdd(f, g){! return f() + g();!};!!

fAdd(five, five);!10

Closures

Closure

Function Environment

HelloMaker

hello greet

function helloMaker(){! var greet = "Hello";! return function(){return greet;};!};!!

var hello = helloMaker();! hello();!!

'Hello'

function helloMaker(){! var greet = "Hello";! return function(){return greet;};!};!!

var hello = helloMaker();! hello();!!

'Hello'

environmentfunction

Counter

get count

function counter(){! var count = 0;! return function(){return ++count;};!};!!

var ids = counter();!!

ids();!1!!

ids();!2

function counter(){! var count = 0;! return function(){return ++count;};!};!!

var ids = counter();!!

ids();!1!!

ids();!2

environmentfunction

Currying

f(a, b, c, d)g(b, c, d)

h(c, d)j(d)

f(a, b, c, d)

Curry

g(b, c, d)

Curry

h(c, d)C

urry

j(d)

ownAdd

f(a, b, c)

Curry

g(b, c)C

urry

h(c)

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

ownAdd(1)(2)(3);!6

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

ownAdd(1)(2)(3);!6

ownAdd

add1

g(b, c)

Curry

h(c)

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

var add1 = ownAdd(1);!add1(2)(3);!6

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

var add1 = ownAdd(1);!add1(2)(3);!6

add1a = 1

add3

h(c)

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

var add3 = ownAdd(1)(2);!add3(3);!6

var ownAdd = function(a){! return function(b){! return function(c){! return a + b + c;! }! }!};!!

var add3 = ownAdd(1)(2);!add3(3);!6

add3

a = 1b = 2

CombinatorsMoses Schönfinkel

andHaskell Curry

BluebirdB f g x = f (g x)

ComposeB f g x = f (g x)

Compose

Function Function Function

Compose

Function Function Function

Square and Add 1

x + 1 x * x

var compose = require(“underscore").compose;!!

var sqAnd1 = compose(! function(x){return x+1;},! function(x){return x*x;}!);!!

sqAnd1(2);!5

Guid

sha1 str counter

var compose = require("underscore").compose,! sha1 = require("node-sha1"),!!function counter(){! var count = 0;! return function(){return ++count;};!};!!function str(s){! return s ? s.toString() : "";!};!!var guid = compose(sha1, str, counter());!!guid();!'356a192b7913b04c54574d18c28d46e6395428ab'!guid();!'da4b9237bacccdf19c0760cab7aec4a8359010b0'

var! _ = require("underscore"),! compose = _.compose;

_.compose = function() {! var funcs = arguments;! return function() {! var args = arguments;! for (var i = funcs.length - 1; i >= 0; i--) {! args = [funcs[i].apply(this, args)];! }! return args[0];! };! };

Compose

Function Function Function

_.compose = function() {! var funcs = arguments;! return function() {! var args = arguments;! for (var i = funcs.length - 1; i >= 0; i--) {! args = [funcs[i].apply(this, args)];! }! return args[0];! };! };

CardinalC f x y = f y x

Flip / WithC f x y = f y x

FlipC f x y = f y x

flip

b a

var flip = require("bilby").flip;!!

function cat(s, t){return s + t;};!!

cat("Hello ", "Mike ");!'Hello Mike '!!

flip(cat)("Hello ")("Mike ");!'Mike Hello '

var flip = require("bilby").flip;!!

function cat(s, t){return s + t;};!!

var post = flip(cat);!!

var messageToMike = post("Mike ");!!

messageToMike("Hello ");!'Hello Mike '!!

messageToMike("Bye ");!'Bye Mike '

var! bilby = require("bilby"),! flip = bilby.flip;

function flip(f) {! return function(a) {! return function(b) {! return f(b, a);! };! };!}

flip

b a

function flip(f) {! return function(a) {! return function(b) {! return f(b, a);! };! };!}

WithC f x y = f y x

Filter_.filter = _.select = function(obj, predicate, context) { var results = []; if (obj == null) return results; if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); each(obj, function(value, index, list) { if (predicate.call(context, value, index, list)) results.push(value); }); return results; };

filter

array function

filter

1, 2, 3 isEven

var filter = require("underscore").filter;!!

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

filter([1, 2, 3], isEven);![ 2 ]!!

[1, 2, 3].filter(isEven);![ 2 ]

var! _ = require("underscore"),! filter = _.filter;

_.filter = _.select = function(obj, predicate, context) {! var results = [];! if (obj == null) return results;! if (nativeFilter && obj.filter === nativeFilter) ! return obj.filter(predicate, context);! each(obj, function(value, index, list) {! if (predicate.call(context, value, index, list))! results.push(value);! });! return results;! };

filter

array function

_.filter = _.select = function(obj, predicate, context) {! var results = [];! if (obj == null) return results;! if (nativeFilter && obj.filter === nativeFilter) ! return obj.filter(predicate, context);! each(obj, function(value, index, list) {! if (predicate.call(context, value, index, list))! results.push(value);! });! return results;! };

FilterWithvar filter = binary( function filter (list, fn) { fn = functionalize(fn); return __filter.call(list, fn); }); var filterWith = flip(filter);

filterWith

arrayfunction

filterWith

1, 2, 3isEven

var filterWith = require("allong.es").allong.es.filterWith;!!function isEven(x){return x%2 === 0;};!var evenOnly = filterWith(isEven);!!evenOnly([1, 2, 3]);![ 2 ]!!evenOnly([42, 113]);![ 42 ]!!evenOnly([2, 1232, 131, 2, 13]);![ 2, 1232, 2 ]

var! allonges = require("allong.es").allong.es,! filterWith = allonges.filterWith

var filter = binary( function filter (list, fn) {! fn = functionalize(fn);! ! return __filter.call(list, fn);!});! ! var filterWith = flip(filter);

filterWith

arrayfunction

var filter = binary( function filter (list, fn) {! fn = functionalize(fn);! ! return __filter.call(list, fn);!});! ! var filterWith = flip(filter);

Multimethods

Environment

Method

Predicate FunctionName

Environment

Method

Predicate FunctionName

(name, predicate)

name

predicate func

tion

var! bilby = require("bilby"),! environment = bilby.environment;

animals

voice

isA sayspeak

var environment = require("bilby").environment;!var animals = environment();!!function voice(type, sound){! return ["The", type, "says", sound].join(" ");!};!!function isA(thing){! return function(obj){! return obj.type == thing;! };!};!!function say(sound){! return function(obj){! console.log(voice(obj.type, sound));! };!};

animals

voice

isA sayspeak

var environment = require("bilby").environment;!var animals = environment();!!function voice(type, sound){! return ["The", type, "says", sound].join(" ");!};!!function isA(thing){! return function(obj){! return obj.type == thing;! };!};!!function say(sound){! return function(obj){! console.log(voice(obj.type, sound));! };!};

method

environment

predicate

function

Animals

voice

cat meowspeak

(speak, cat)

speak

cat

meo

w

var animals = animals.method(! “speak",! isA(“cat"),! say("meow"));!var animals = animals.method(! “speak",! isA(“dog"),! say("woof"));!!

animals.speak({type: "dog"});!The dog says woof!!

animals.speak({type: "cat"});!The cat says meow

Animals

voice

cat meowspeak

(speak, cat)

speak

cat

meo

w

var animals = animals.method(! “speak",! isA(“cat"),! say("meow"));!var animals = animals.method(! “speak",! isA(“dog"),! say("woof"));!!

animals.speak({type: "dog"});!The dog says woof!!

animals.speak({type: "cat"});!The cat says meow

namepredicate

function

environment

“What does the fox say?”

var animals = animals.method(! "speak",! isA("fox"),! say(“Wa-pa-pa-pa-pa-pa-pow!")!);!!

animals.speak({type:"fox"});!The fox says Wa-pa-pa-pa-pa-pa-pow!

Dante, The Divine Comedy Canto 24

A longer ladder yet remains to scale.

Functional JavaScriptMichael Fogus

JavaScript AllongeReginald Braithwaite

Learn You a Haskell for Great Good!

Miran Lipovača

The Joy of ClojureMichael Fogus$Chris Houser

Nietzsche, Human, All Too Human Aphorism 633

Now we will no longer concede so easily that anyone has the truth.

Thank you.

Mike Harris@MikeMKH!http://comp-phil.blogspot.com/

top related