Slide 1

Slide 1 text

Recursion, Iteration, & JS: A lo t @AnjanaVakil ❤ JSHeroes 2018

Slide 2

Slide 2 text

Bună! Mă c e ă @AnjanaVakil

Slide 3

Slide 3 text

location data platform for developers maps, search, navigation web, iOS, Android, Unity...

Slide 4

Slide 4 text

so m u t e I ♥ The Recurse Center recurse.com outreachy.org

Slide 5

Slide 5 text

I ♥ programming paradigms le ’s e d ! youtu.be/Pg3UeB-5FdA

Slide 6

Slide 6 text

t i s a f o star-crossed paradigms

Slide 7

Slide 7 text

Iteration v Recursion

Slide 8

Slide 8 text

Iteration Imperative Repetitive Stateful

Slide 9

Slide 9 text

Iteration Imperative Repetitive Stateful © Columbia Pictures 1993 - image via IMDb

Slide 10

Slide 10 text

Recursion Functional Self-referential Stateless © Warner Brothers 2010 - image via IMDb

Slide 11

Slide 11 text

Recursion Functional Self-referential Stateless © Warner Brothers 2010 - image via IMDb

Slide 12

Slide 12 text

Iteration v Recursion

Slide 13

Slide 13 text

t o r i m , bo l e dignity

Slide 14

Slide 14 text

bu h o t efficiency?

Slide 15

Slide 15 text

Jon n B o “Pro m g Ae h s e n ro k in n e t s” youtu.be/JjDsP5n2kSM - h/t Yo h

Slide 16

Slide 16 text

You might optimize for speed… You might optimize for space... But… there's a third thing you might want to optimize for, which is: years of your life required per program implementation. This is more important than those other things... or certainly equally important. Jon n B o “Pro m g Ae h s e n ro k in n e t s” youtu.be/JjDsP5n2kSM - h/t Yo h “ ”

Slide 17

Slide 17 text

Machine Efficiency Time Space Human Efficiency Writing Reading Maintenance v

Slide 18

Slide 18 text

in JavaScript we ur n

Slide 19

Slide 19 text

yu , I’m u n Shakespeare © 20th Century Fox 1996 - image via IMDb

Slide 20

Slide 20 text

bu h t ha happy ending

Slide 21

Slide 21 text

JS

Slide 22

Slide 22 text

Act I: Ite on, bu t i

Slide 23

Slide 23 text

> var simpleTree = makeTree(simpleTreeNode); We l ♥t e function simpleTreeNode(value) { return { value: value, left: undefined, right: undefined }; } function makeTree(nodeType) { var root = nodeType(0); root.left = nodeType(1); root.left.left = nodeType(2); root.right = nodeType(3); root.right.left = nodeType(4); root.right.right = nodeType(5); root.right.right.right = nodeType(6); return root; } 0 1 2 3 4 5 6

Slide 24

Slide 24 text

Recursive tree traversal function recursiveTraverse(tree) { // base case if (!tree) return; // recursive case console.log(tree.value); recursiveTraverse(tree.left); recursiveTraverse(tree.right); } > recursiveTraverse(simpleTree); 0 1 2 3 4 5 6

Slide 25

Slide 25 text

Recursive tree traversal function recursiveTraverse(tree) { // base case if (!tree) return; // recursive case console.log(tree.value); recursiveTraverse(tree.left); recursiveTraverse(tree.right); } > recursiveTraverse(simpleTree); 0 1 2 3 4 5 6 in iv e d & w i ! === hu -ef en

Slide 26

Slide 26 text

Iterative tree traversal function iterativeTraverse(tree) { var todo = [tree]; while (todo.length) { var next = todo.shift(); if (next) { console.log(next.value); todo.unshift(next.left); todo.push(next.right); } } } > iterativeTraverse(simpleTree); 0 1 2 3 4 5 6

Slide 27

Slide 27 text

Iterative tree traversal function iterativeTraverse(tree) { var todo = [tree]; while (todo.length) { var next = todo.shift(); if (next) { console.log(next.value); todo.unshift(next.left); todo.push(next.right); } } } > iterativeTraverse(simpleTree); 0 1 2 3 4 5 6 ru j s e l, bu t i t i :/

Slide 28

Slide 28 text

wo n’t o t u t “fo h a of t e…”

Slide 29

Slide 29 text

JS Ite on ES6: ● Iterables via [Symbol.iterator] ● Iterators via next() ● Generators via function* and yield ● for…of loops

Slide 30

Slide 30 text

Iterables function iterableTreeNode(value) { let node = { value: value, left: undefined, right: undefined }; function recurseyIterator() { } node[Symbol.iterator]= recurseyIterator; return node; } function recurTraverse(tree) { if (!tree) return; // base case console.log(tree.value); // recursive case recurTraverse(tree.left); recurTraverse(tree.right); } + Recursion

Slide 31

Slide 31 text

Iterables function iterableTreeNode(value) { let node = { value: value, left: undefined, right: undefined }; function recurseyIterator() { } node[Symbol.iterator]= recurseyIterator; return node; } function recurTrav(tree) { console.log(tree.value); // recursive case if (tree.left) recurTrav(tree.left); if (tree.right) recurTrav(tree.right); // base case (no children): just return } + Recursion

Slide 32

Slide 32 text

Iterables function iterableTreeNode(value) { let node = { value: value, left: undefined, right: undefined }; function recurseyIterator() { // recursive case // base case: finish iteration } node[Symbol.iterator]= recurseyIterator; return node; } function recurTrav(tree) { console.log(tree.value); // recursive case if (tree.left) recurTrav(tree.left); if (tree.right) recurTrav(tree.right); // base case (no children): just return } + Recursion

Slide 33

Slide 33 text

Iterables function iterableTreeNode(value) { let node = { value: value, left: undefined, right: undefined }; function* recurseyIterator() { yield node.value; // recursive case if (node.left) yield* node.left; if (node.right) yield* node.right; // base case: finish iteration } node[Symbol.iterator]= recurseyIterator; return node; } function recurTrav(tree) { console.log(tree.value); // recursive case if (tree.left) recurTrav(tree.left); if (tree.right) recurTrav(tree.right); // base case (no children): just return } + Recursion

Slide 34

Slide 34 text

Iterables function iterableTreeNode(value) { let node = { value: value, left: undefined, right: undefined }; function* recurseyIterator() { yield node.value; // recursive case if (node.left) yield* node.left; if (node.right) yield* node.right; // base case: finish iteration } node[Symbol.iterator]= recurseyIterator; return node; } > let betterTree = makeTree(iterableTreeNode); > for (let val of betterTree) console.log(val); 0 1 2 3 4 5 6

Slide 35

Slide 35 text

JS It(er) ge b r: github.com/tc39/proposal-async-iteration tc39.github.io/ecma262 ● Async Iterables via [Symbol.asyncIterator] ● AsyncIterators via next().then() ● Async Generators ● for await…of loops

Slide 36

Slide 36 text

Iteration JavaScript Recursion = Human-efficient Iteration + +

Slide 37

Slide 37 text

Act II: Rec on, bu r ma

Slide 38

Slide 38 text

Recursion: the dream // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 a dream within a dream within a dream within a dream

Slide 39

Slide 39 text

Recursion: the dream // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 a dream within a dream within a dream within a dream $ node recursiveInception.js 30 a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream 1 2 3 4 5 6 7 8 9 10 11

Slide 40

Slide 40 text

Recursion: the dream // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3000 a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a … you get the idea 1 2 3 4 5 6 7 8 9 10 11

Slide 41

Slide 41 text

Recursion: the dream // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11

Slide 42

Slide 42 text

Recursion: the reality // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 /home/anjana/JSHeroes/recursiveInception.js:4 const recursiveInception = (n) => { ^ RangeError: Maximum call stack size exceeded at recursiveInception (recursiveInception.js:4:28) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) 1 2 3 4 5 6 7 8 9 10 11

Slide 43

Slide 43 text

Recursion: the reality // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 /home/anjana/JSHeroes/recursiveInception.js:4 const recursiveInception = (n) => { ^ RangeError: Maximum call stack size exceeded at recursiveInception (recursiveInception.js:4:28) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) at recursiveInception (recursiveInception.js:6:16) 1 2 3 4 5 6 7 8 9 10 11

Slide 44

Slide 44 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); 1 2 3 4 5 6 7 8 9 10 11

Slide 45

Slide 45 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11

Slide 46

Slide 46 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 ^ s a k (li d e )

Slide 47

Slide 47 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 f a > recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream";

Slide 48

Slide 48 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = recursiveInception(1); return dreams + " within a dream"; )^

Slide 49

Slide 49 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(1) let dreams = recursiveInception(0); return dreams + " within a dream"; )^

Slide 50

Slide 50 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(1) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(0) return "a dream"; )^

Slide 51

Slide 51 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(1) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(0) return "a dream"; ( ^

Slide 52

Slide 52 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = recursiveInception(1); return dreams + " within a dream"; recursiveInception(1) let dreams = "a dream"; return dreams + " within a dream"; ( ^

Slide 53

Slide 53 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = recursiveInception(2); return dreams + " within a dream"; recursiveInception(2) let dreams = "a dream within a dream"; return dreams + " within a dream"; ( ^

Slide 54

Slide 54 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(3) let dreams = "a dream within a dream within a dream" ; return dreams + " within a dream"; )^

Slide 55

Slide 55 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 3 a dream within a dream within a dream within a dream 1 2 3 4 5 6 7 8 9 10 11

Slide 56

Slide 56 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11

Slide 57

Slide 57 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11

Slide 58

Slide 58 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(30000) let dreams=recursiveInception(29999); return dreams + " within a dream";

Slide 59

Slide 59 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(30000) let dreams=recursiveInception(29999); return dreams + " within a dream"; recursiveInception(29999) let dreams=recursiveInception(29998); return dreams + " within a dream"; )^

Slide 60

Slide 60 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(30000) let dreams=recursiveInception(29999); return dreams + " within a dream"; recursiveInception(29999) let dreams=recursiveInception(29998); return dreams + " within a dream"; recursiveInception(29998) let dreams=recursiveInception(29997); return dreams + " within a dream"; )^

Slide 61

Slide 61 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(30000) let dreams=recursiveInception(29999); return dreams + " within a dream"; recursiveInception(29999) let dreams=recursiveInception(29998); return dreams + " within a dream"; recursiveInception(29998) let dreams=recursiveInception(29997); return dreams + " within a dream"; )^ recursiveInception(29997) let dreams=recursiveInception(29996); return dreams + " within a dream";

Slide 62

Slide 62 text

Recursion ca s k // recursiveInception.js 'use strict'; const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } const depth = parseInt(process.argv[2]); console.log(recursiveInception(depth)); $ node recursiveInception.js 30000 RangeError: Maximum call stack size exceeded 1 2 3 4 5 6 7 8 9 10 11 recursiveInception(30000) let dreams=recursiveInception(29999); return dreams + " within a dream"; recursiveInception(29999) let dreams=recursiveInception(29998); return dreams + " within a dream"; recursiveInception(29998) let dreams=recursiveInception(29997); return dreams + " within a dream"; recursiveInception(29997) let dreams=recursiveInception(29996); return dreams + " within a dream"; :(

Slide 63

Slide 63 text

wo n’t o to r e wi t a n t f a s?

Slide 64

Slide 64 text

JS Ta l Op i z i ● Implementation feature of (some*) JS engines ● Lets us ♻ stack frames: don’t need to “remember” anything from calling context ● Requires call in tail position: “proper tail calls” in ES6

Slide 65

Slide 65 text

Tail Recursion const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e

Slide 66

Slide 66 text

Tail Recursion const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { } Ta l-re s e

Slide 67

Slide 67 text

Tail Recursion const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e us e p n ^ to h e r o

Slide 68

Slide 68 text

const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e us e p n ^ to h e r o ^ ca t m a f Tail Recursion

Slide 69

Slide 69 text

const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e us um or ^ to “re b ” hi r Tail Recursion

Slide 70

Slide 70 text

const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e us um or ^ to “re b ” hi r in a c . ^ is ca Tail Recursion

Slide 71

Slide 71 text

const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e ^ re s e l in “ta si ” Tail Recursion

Slide 72

Slide 72 text

const recursiveInception = (n) => { if (n === 0) return "a dream"; let dreams = recursiveInception(n-1); return dreams + " within a dream"; } f o s e w ^ af r u s al Not -re s e const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } Ta l-re s e ^ re s e l la t g f o s Tail Recursion

Slide 73

Slide 73 text

Ta l Op i z i const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3);

Slide 74

Slide 74 text

Ta l Op i z i const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream");

Slide 75

Slide 75 text

Ta l Op i z i const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); )^ incept(3, "a dream") return incept(2, "a dream within a dream");

Slide 76

Slide 76 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(3, "a dream") return incept(2, "a dream within a dream"); Ta l Op i z i incept(2, "a dream within a dream") return incept(1, "a… w… within a dream"); )^

Slide 77

Slide 77 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(3, "a dream") return incept(2, "a dream within a dream"); Ta l Op i z i incept(2, "a dream within a dream") return incept(1, "a… w… within a dream"); ♻

Slide 78

Slide 78 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(2, "a dream within a dream") return incept(1, "a… w… within a dream"); Ta l Op i z i

Slide 79

Slide 79 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(2, "a dream within a dream") return incept(1, "a… w… within a dream"); Ta l Op i z i )^ incept(1, "a dream within a dream within a dream") return incept(0, "a… w… w… within a dream");

Slide 80

Slide 80 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(2, "a dream within a dream") return incept(1, "a… w… within a dream"); Ta l Op i z i incept(1, "a dream within a dream within a dream") return incept(0, "a… w… w… within a dream"); ♻

Slide 81

Slide 81 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(1, "a dream within a dream within a dream") return incept(0, "a… w… w… within a dream"); Ta l Op i z i

Slide 82

Slide 82 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(1, "a dream within a dream within a dream") return incept(0, "a… w… w… within a dream"); Ta l Op i z i incept(0, "a dream within a dream within a dream within a dream") return "a dream within a dream within a dream within a dream"; )^

Slide 83

Slide 83 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(1, "a dream within a dream within a dream") return incept(0, "a… w… w… within a dream"); Ta l Op i z i incept(0, "a dream within a dream within a dream within a dream") return "a dream within a dream within a dream within a dream"; ♻

Slide 84

Slide 84 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(0, "a dream within a dream within a dream within a dream") return "a dream within a dream within a dream within a dream"; Ta l Op i z i

Slide 85

Slide 85 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return incept(3, "a dream"); incept(0, "a dream within a dream within a dream within a dream") return "a dream within a dream within a dream within a dream"; ( ^ Ta l Op i z i

Slide 86

Slide 86 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); tailRecursiveInception(3) return "a dream within a dream within a dream within a dream"; )^ Ta l Op i z i

Slide 87

Slide 87 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } > tailRecursiveInception(3); a dream within a dream within a dream within a dream Ta l Op i z i

Slide 88

Slide 88 text

const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } console.log(tailRecursiveInception(3)); let n = 3; let dreams = "a dream"; while (n > 0) { dreams += " within a dream"; n--; } console.log(dreams); Recursion + T O ≈ Iteration ^ w i t ke s ^ ru s li h

Slide 89

Slide 89 text

T O L // tailRecursiveInception.js 'use strict'; const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } const depth = parseInt(process.argv[2]); console.log(tailRecursiveInception(depth)); 1 2 3 4 5 6 7 8 9 10 11 12 13

Slide 90

Slide 90 text

// tailRecursiveInception.js 'use strict'; const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } const depth = parseInt(process.argv[2]); console.log(tailRecursiveInception(depth)); 1 2 3 4 5 6 7 8 9 10 11 12 13 $ node tailRecursiveInception.js 30000 T O L

Slide 91

Slide 91 text

// tailRecursiveInception.js 'use strict'; const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } const depth = parseInt(process.argv[2]); console.log(tailRecursiveInception(depth)); 1 2 3 4 5 6 7 8 9 10 11 12 13 $ node tailRecursiveInception.js 30000 /home/anjana/JSHeroes/tailRecursiveInception.js:5 const incept = (n, dreams) => { ^ RangeError: Maximum call stack size exceeded at incept (tailRecursiveInception.js:5:18) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) T O L

Slide 92

Slide 92 text

// tailRecursiveInception.js 'use strict'; const tailRecursiveInception = (n) => { const incept = (n, dreams) => { if (n === 0) return dreams; return incept(n-1, dreams+" within a dream"); } return incept(n, "a dream"); } const depth = parseInt(process.argv[2]); console.log(tailRecursiveInception(depth)); 1 2 3 4 5 6 7 8 9 10 11 12 13 $ node tailRecursiveInception.js 30000 /home/anjana/JSHeroes/tailRecursiveInception.js:5 const incept = (n, dreams) => { ^ RangeError: Maximum call stack size exceeded at incept (tailRecursiveInception.js:5:18) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) at incept (tailRecursiveInception.js:7:12) li ! be y ! T O L

Slide 93

Slide 93 text

Ta l Op i z i Feature of (some*) JS engines

Slide 94

Slide 94 text

Ta l Op i z i Feature of (some*) JS engines * On a c e; mo do im m T O kangax.github.io/compat-table/es6/#test-proper_tail_calls_(tail_call_optimisation) ● Webkit/Safari has it: webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit/ ● V8/Chromium/Node had it (w/ flag), removed it: bugs.chromium.org/p/v8/issues/detail?id=4698

Slide 95

Slide 95 text

Ta l Op i z i Feature of (some*) JS engines * On a c e; mo do im m T O kangax.github.io/compat-table/es6/#test-proper_tail_calls_(tail_call_optimisation) ● Webkit/Safari has it: webkit.org/blog/6240/ecmascript-6-proper-tail-calls-in-webkit/ ● V8/Chromium/Node had it (w/ flag), removed it: bugs.chromium.org/p/v8/issues/detail?id=4698 Hot d ed ur ; di s o s o n ! ● TCO issues explained in V8 blog: v8project.blogspot.ro/2016/04/es6-es7-and-beyond.html ● TC39 proposal for explicit tail call syntax (inactive): github.com/tc39/proposal-ptc-syntax ● Ongoing discussion/proposal for WebAssembly: github.com/WebAssembly/tail-call

Slide 96

Slide 96 text

$ nvm use 6 Now using node v6.12.3 T O L

Slide 97

Slide 97 text

$ nvm use 6 Now using node v6.12.3 $ node --harmony_tailcalls tailRecursiveInception.js 30000 T O L

Slide 98

Slide 98 text

$ nvm use 6 Now using node v6.12.3 $ node --harmony_tailcalls tailRecursiveInception.js 30000 a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within a dream within ………………….. T O L

Slide 99

Slide 99 text

Recursion JavaScript Iteration = Machine-efficient Recursion + +

Slide 100

Slide 100 text

Iteration v Recursion

Slide 101

Slide 101 text

JS Iteration Recursion

Slide 102

Slide 102 text

Fur r a n : Exploring JS b D . Axe R c ay exploringjs.com ● ES6 - Iteration: Ch. 17, 21, 22; TCO: Ch. 27 ● ES2018-ES2019: Asynchronous Iteration MDN developer.mozilla.org ● JavaScript>Reference>Iteration_protocols ● JavaScript>Guide>Functions>Recursion

Slide 103

Slide 103 text

Mulțum ! JSHeroes organizers & Ioana Chiorean Mapbox The Recurse Center community Max Rabkin @An a V ki ❤ an @ma x.co