06 map reduce

33
Let’s talk about lambda

Upload: crgwbr

Post on 15-Jan-2015

60 views

Category:

Technology


0 download

DESCRIPTION

Examples and concept from the excellent Clojure talk, "A monad is not a burrito." http://www.youtube.com/watch?v=46Z7Hq4fhN0

TRANSCRIPT

Page 1: 06 Map Reduce

Let’s talk about lambda

Page 2: 06 Map Reduce

Why care?

Page 3: 06 Map Reduce

NULL is troublesome The dog breeder example

Page 4: 06 Map Reduce
Page 5: 06 Map Reduce

var colleen, richard;!colleen = { pet: { mother: { owner: "Sarah" } }};!richard = { pet: null};

Page 6: 06 Map Reduce

Given a person, return its pet’s mother’s owner.

Page 7: 06 Map Reduce

function findBreeder(person) { return person.pet.mother.owner;}

Page 8: 06 Map Reduce

function findBreeder(person) { return person.pet.mother.owner;}!>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);Exception: "Can not read property 'mother' of undefined"

Page 9: 06 Map Reduce

function findBreeder(person) { if (!person) { return null; }! if (!person.pet) { return null; } if (!person.pet.mother) { return null; }! return person.pet.mother.owner;}

Page 10: 06 Map Reduce

>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null

Page 11: 06 Map Reduce

LISTS are troublesome The investment broker example

Page 12: 06 Map Reduce

Broker Clients Investment Types Markets Balance

Page 13: 06 Map Reduce

var colin = { clients: [ { name: "Fred", investments: [ { name: "Shares", markets: [ { name: "Japan", value: 7000 }, { name: "America", value: 8888 } ] }, { name: "Gold", markets: [ { name: "China", value: 3333 }, ] } ] } ]};

Page 14: 06 Map Reduce

Find the sum of all of an investors’s client’s investments.

Page 15: 06 Map Reduce

sumInvestments = (clients) -> values = [] foreach client in clients: foreach investment in client.investments foreach market in investment.markets values.push(market.balance) return sum(values)

Page 16: 06 Map Reduce

function sumInvestments (clients) { var i, j, k; var investments, markets; var value = 0;! for (i = 0; i < clients.length; i++) { investments = clients[i].investments;! for (j = 0; j < investments.length; j++) { markets = investments[j].markets;! for (k = 0; k < markets.length; k++) { value += markets[k].value } } }! return value;};

Page 17: 06 Map Reduce
Page 18: 06 Map Reduce

(multi-layer list iteration) vs. (null checking) !

What’s the common thread?

Page 19: 06 Map Reduce

no code duplication !

lots of concept duplication

Page 20: 06 Map Reduce

function call_unless_null(val, fn) { if (val !== null) { return fn(val); }! return null;}!function findBreeder(person) { return call_unless_null(person, function(person) { return call_unless_null(person.pet, function(pet) { return call_unless_null(pet.mother, function(mother) { return mother.owner; }); }); });}

Page 21: 06 Map Reduce

>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null

Page 22: 06 Map Reduce

Still too much duplication.

Page 23: 06 Map Reduce

function reduce(iter, memo, fn) { for (var i = 0; i < iter.length; i++) { memo = fn(memo, iter[i]); }! return memo;}!function get_unless_null(obj, key) { if (obj !== null && obj !== undefined) { return obj[key]; } return null;}!function findBreeder(person) { return reduce(['pet', 'mother', ‘owner’], person, get_unless_null);}

Page 24: 06 Map Reduce

>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null

Page 25: 06 Map Reduce

function sumInvestments(clients) { var values;! values = flat_map(clients, function(client) { return flat_map(client.investments, function(investment) { return flat_map(investment.markets, function(market) { return market.value; }); }); });! return sum(values);};

Page 26: 06 Map Reduce

function map(iter, fn) { var out = [], val;! for (var i = 0; i < iter.length; i++) { out[i] = fn(iter[i]); }! return out;}!function flat_map(iter, fn) { iter = map(iter, fn); return reduce(iter, [], function(memo, item) { return memo.concat(item); });}!function sum(list) { return reduce(list, 0, function(memo, num) { return memo + num; });}

Page 27: 06 Map Reduce

function sumInvestments(clients) { var v, fn;! fn = function(arr, key) { return flat_map(arr, function(item) { return get_unless_null(item, key); }); };! v = reduce(clients, ['investments', 'markets', 'value'], fn); return sum(v);};

Page 28: 06 Map Reduce

What have we accomplished?

Page 29: 06 Map Reduce

function sumInvestments (clients) { var i, j, k; var investments, markets; var value = 0;! for (i = 0; i < clients.length; i++) { investments = clients[i].investments;! for (j = 0; j < investments.length; j++) { markets = investments[j].markets;! for (k = 0; k < markets.length; k++) { value += markets[k].value } } }! return value};!function sumInvestments(clients) { var v;! v = reduce(clients, ['investments', 'markets', 'value'], function(arr, key) { return flat_map(arr, function(item) { return item[key]; }); });! return sum(v);};

ugly

awesome

Page 30: 06 Map Reduce

function findBreeder(person) { if (!person) { return null; }! if (!person.pet) { return null; } if (!person.pet.mother) { return null; }! return person.pet.mother.owner;}!!!function findBreeder(person) { return reduce(get_unless_null, person, ['pet', 'mother', 'owner']);}

ugly

awesome

Page 31: 06 Map Reduce

Concept duplication is just masked code duplication

Page 32: 06 Map Reduce

Repeating patterns are hint

Page 33: 06 Map Reduce

Higher-order functions make all this possible