functional javascript, cvjs

71
Talk Functional Javascript! //+ CV.js :: September 18th, 2013 Kevin Welcher

Upload: kaw2

Post on 12-May-2015

669 views

Category:

Technology


2 download

DESCRIPTION

Javascript Meetup in Charlottesville for CVjs. http://www.meetup.com/Central-Virginia-Javascript-Enthusiasts-CVJSE/events/132911552/

TRANSCRIPT

Page 1: Functional Javascript, CVjs

Talk Functional Javascript!

//+ CV.js :: September 18th, 2013

Kevin Welcher

Page 2: Functional Javascript, CVjs

Shout Out

Page 3: Functional Javascript, CVjs

Shout Out

Something about Camp?

Page 4: Functional Javascript, CVjs

10k Feet

• [Underscore.js / Lodash.js]

• Functional Concepts

• Composition

• Currying

• [Demo]

Page 5: Functional Javascript, CVjs

Underscore.jsLodash.js

Page 6: Functional Javascript, CVjs

Highlights

• reduce

• map

• pluck

• filter

• find

Page 7: Functional Javascript, CVjs

reduce

• The grandaddy, most iterators can be made out of reduce

• “Reduce a list to a new object”

Page 8: Functional Javascript, CVjs

map

• Bread and butter iterator

• Used to transform a list of elements from one type to another

• Whatever is returned within the iterator is the new object

Page 9: Functional Javascript, CVjs

pluck

• Iterates over a list of objects and returns a new list made of the specified property from each object

• A common use for map

• IE: plucking the name from an array of people objects

Page 10: Functional Javascript, CVjs

filter

• Only allows values that pass a predicate into the new list

• As with all these methods, it returns copies of the data

Page 11: Functional Javascript, CVjs

find

• Accepts a predicate and returns the first item that passes the predicate

Page 12: Functional Javascript, CVjs

Much, much more...• Many predicates

(isArray, isNull, ...)

• keys / values

• groupBy

• result

• array methods

• union / intersection

• chain / compose

• extend / defaults

• simple templates

• pick / omit

Page 13: Functional Javascript, CVjs

FP vs OO

• The language of the... language

• How complexity is hidden

• How data is stored

Page 14: Functional Javascript, CVjs

Functional Concepts

Page 15: Functional Javascript, CVjs

Function purity

• Deterministic

• Does not depend on external state

• Does not depend on IO

• Does not cause side effects

Page 16: Functional Javascript, CVjs

Function purityvar View = Backbone.View.extend({ initialize: function() { this.generateList(); }, generateList: function() { this.list = new Backbone.Collection([ {name: 'sally'}, {name: 'joe'} ]); }});

Page 17: Functional Javascript, CVjs

Function purityvar View = Backbone.View.extend({ initialize: function() { this.list = this.generateList(); }, generateList: function() { return new Backbone.Collection([ {name: 'sally'}, {name: 'joe'} ]); }});

Page 18: Functional Javascript, CVjs

Functions as data

• First class citizens

• Identified by their returns

• Modifiable

Page 19: Functional Javascript, CVjs

Functions as building blocks

Functions which consume the return value of the function that follows.

Composition:

Page 20: Functional Javascript, CVjs

Functions as building blocks

a() b() c()

a(b(c(x))) === compose(a, b, c)(x)

Composition

Page 21: Functional Javascript, CVjs

Functions as building blocks

function add1 (x) { return x + 1;}

var add3 = compose(add1, add1, add1);

add3(0);

//> 3

Page 22: Functional Javascript, CVjs

Functions as building blocks

function add1 (x) { return x + 1;}

var add3 = compose(add1, add1, add1);

add3(0);

//> 3

0

Page 23: Functional Javascript, CVjs

Functions as building blocks

function add1 (x) { return x + 1;}

var add3 = compose(add1, add1, add1);

add3(0);

//> 3

01

Page 24: Functional Javascript, CVjs

Functions as building blocks

function add1 (x) { return x + 1;}

var add3 = compose(add1, add1, add1);

add3(0);

//> 3

012

Page 25: Functional Javascript, CVjs

Functions as building blocks

function add1 (x) { return x + 1;}

var add3 = compose(add1, add1, add1);

add3(0);

//> 3

0123

Page 26: Functional Javascript, CVjs

Functions as building blocks

function not (x) { return !x;}

var boolify = compose(not, not);

not(not({}));boolify({});

//> true

Page 27: Functional Javascript, CVjs

Functions as building blocks

function addTitle (x) { return ‘Mr. ‘ + x;}

function addSalutation (x) { return ‘G’day, ‘ + x;}

var meetAndGreet = compose(addSalutation, addTitle);

addSalutation(addTitle('Baggins'));meetAndGreet('Baggins');

//> G’day, Mr. Baggins

Page 28: Functional Javascript, CVjs

Functions as building blocks

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

var add1 = compose(???);

//> profit

Page 29: Functional Javascript, CVjs

Currying

“Taking a function that takes multiple arguments and transforming it to a chain of functions that accept a single

argument.” - Wikipedia

Page 30: Functional Javascript, CVjs

Notation

//+ <method name> :: type -> type -> type

Page 31: Functional Javascript, CVjs

Notation

//+ <method name> :: type -> type -> type

A function that take takes an argument and returns a value of type

Page 32: Functional Javascript, CVjs

Notation

//+ <method name> :: type -> type -> type

A function that take takes an argument and returns a value of type

integer -> integer

A function that takes in a single argument of type integer

The return type of integer. Since nothing follows, it is the final return

Page 33: Functional Javascript, CVjs

Notation

//+ <method name> :: type -> type -> type

A function that take takes an argument and returns a value of type

Page 34: Functional Javascript, CVjs

Notation

//+ <method name> :: type -> type -> type

The ultimate return value of a function

Page 35: Functional Javascript, CVjs

//+ not :: a -> boolean

function not (x) { return !x;}

not(true) //> false

Page 36: Functional Javascript, CVjs

//+ not :: a -> boolean

function not (x) { return !x;}

not(true) //> false

The a (or any other lower case letter) means we don’t care about the type.

Page 37: Functional Javascript, CVjs

//+ add :: a, a -> a function add(x, y) { return x + y;}

add(1, 2); //> 3

Page 38: Functional Javascript, CVjs

//+ add :: a, a -> a function add(x, y) { return x + y;}

add(1, 2); //> 3

I am abusing notation :(

Page 39: Functional Javascript, CVjs

“Taking a function that takes multiple arguments and transforming it to a chain of functions that accept a single

argument.” - Wikipedia

Page 40: Functional Javascript, CVjs

//+ add :: a, a -> a

//+ add :: a -> a -> a

Page 41: Functional Javascript, CVjs

//+ add :: a -> a -> a

function add(x) { return function (y) { return x + y; };}

add(1)(2); //> 3

ed

Page 42: Functional Javascript, CVjs

//+ add :: a -> a -> a

function add(x) { return function (y) { return x + y; };}

add(1)(2); //> 3

ed

Page 43: Functional Javascript, CVjs

//+ add :: a -> a -> a

//+ add :: 1 -> a -> a

//+ add1 :: integer -> integervar add1 = add(1);

add1(2); //> 3

Page 44: Functional Javascript, CVjs

//+ add :: a -> a -> a

//+ add :: ‘Mr. ‘ -> a -> a //+ addTitle :: string -> stringvar addTitle = add('Mr. ');

addTitle('Baggins');//> Mr. Baggins

Page 45: Functional Javascript, CVjs

Problem

Page 46: Functional Javascript, CVjs

That _ is ugly

//+ add :: a -> a -> a

function add(x) { return function (y) { return x + y; };}

add(1)(2); //> 3

Page 47: Functional Javascript, CVjs

autoCurry

A custom function that automatically curries for you.

For each parameter of a function, it returns a new function.

Page 48: Functional Javascript, CVjs

That _ is ugly

//+ add :: a -> a -> a

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

add(1, 2); //> 3add(1)(2); //> 3 Awww yissss

Page 49: Functional Javascript, CVjs

Cool Story Bru...

Page 50: Functional Javascript, CVjs

Let Me Convince You With...

Page 51: Functional Javascript, CVjs

More Examples!

Page 52: Functional Javascript, CVjs

reduce

//+ reduce :: fn -> a -> array -> avar reduce = function (fn, start, list) { // ... }.autoCurry();

Page 53: Functional Javascript, CVjs

reduce

//+ reduce :: fn -> a -> array -> avar reduce = function (fn, start, list) { // ... }.autoCurry();

function (cnrt, val, index, list) { // ...}

Page 54: Functional Javascript, CVjs

Sum all the numbers in a list?

Page 55: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (crnt, val, index, list) { return crnt + val;}, 0, items);

//> 6

Page 56: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (crnt, val, index, list) { return crnt + val;}, 0, items);

//> 6

We don’t use these two arguments so we can omit them

Page 57: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (crnt, val) { return crnt + val;}, 0, items);

//> 6

Page 58: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (crnt, val) { return crnt + val;}, 0, items);

//> 6

This function looks familiar...

Page 59: Functional Javascript, CVjs

//+ add :: a -> a -> a

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

Page 60: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (x, y) { return x + y;}, 0, items);

//> 6

Page 61: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(function (x, y) { return x + y;}, 0, items);

//> 6 Instead of inlining the function, just pass

the function’s pointer

Page 62: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(add, 0, items);

//> 6

Page 63: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: fn -> a -> array -> areduce(add, 0, items);

//> 6

Cool! But isn’t reduce curried? Can we make this into a generic function?

Page 64: Functional Javascript, CVjs

var items = [1, 2, 3];

//+ reduce :: add -> 0 -> array -> a//+ sum :: array -> integervar sum = reduce(add, 0);

sum(items);//> 6

Page 65: Functional Javascript, CVjs

Demo

https://gist.github.com/kaw2k/6312261

Page 66: Functional Javascript, CVjs

Lessons Learned?

Page 67: Functional Javascript, CVjs

Keep your methods short and to the point

It is easier to build things if your building blocks are small

Page 68: Functional Javascript, CVjs

Stick your data as the last parameter

reduce = function (fn, starting value, data)

function (general, ..., specific)

Page 69: Functional Javascript, CVjs

Optional parameters are hard

Make a general function and curry it to take optional stuff

Page 70: Functional Javascript, CVjs

Functional purity is pretty cool

• Easier to maintain

• Easier to reason

• Easier to test

• Easier to transport

Page 71: Functional Javascript, CVjs

Obligatory Marketing

(We are hiring)