06 Map Reduce
-
Upload
crgwbr -
Category
Technology
-
view
60 -
download
0
description
Transcript of 06 Map Reduce
Let’s talk about lambda
Why care?
NULL is troublesome The dog breeder example
var colleen, richard;!colleen = { pet: { mother: { owner: "Sarah" } }};!richard = { pet: null};
Given a person, return its pet’s mother’s owner.
function findBreeder(person) { return person.pet.mother.owner;}
function findBreeder(person) { return person.pet.mother.owner;}!>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);Exception: "Can not read property 'mother' of undefined"
function findBreeder(person) { if (!person) { return null; }! if (!person.pet) { return null; } if (!person.pet.mother) { return null; }! return person.pet.mother.owner;}
>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null
LISTS are troublesome The investment broker example
Broker Clients Investment Types Markets Balance
var colin = { clients: [ { name: "Fred", investments: [ { name: "Shares", markets: [ { name: "Japan", value: 7000 }, { name: "America", value: 8888 } ] }, { name: "Gold", markets: [ { name: "China", value: 3333 }, ] } ] } ]};
Find the sum of all of an investors’s client’s investments.
sumInvestments = (clients) -> values = [] foreach client in clients: foreach investment in client.investments foreach market in investment.markets values.push(market.balance) return sum(values)
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;};
(multi-layer list iteration) vs. (null checking) !
What’s the common thread?
no code duplication !
lots of concept duplication
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; }); }); });}
>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null
Still too much duplication.
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);}
>>> findBreeder(colleen);"Sarah"!>>> findBreeder(richard);null
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);};
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; });}
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);};
What have we accomplished?
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
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
Concept duplication is just masked code duplication
Repeating patterns are hint
Higher-order functions make all this possible