const add = (a, b) => {
return a + b;
}
No base case.
No recursive case.
This is, of course, how you’d actually implement this function in Javascript.
const add = (a, b) => {
if (b === 0) {
return a;
} else {
return add(a + b, 0); // 🙄
}
}
Has a base case. (b === 0
)
Has a recursive case. (Calls add
)
But kinda cheating because the addition is not done by the recursion.
const add = (a, b) => {
if (b === 0) {
return a;
} else {
return 1 + add(a, b - 1);
}
}
Each recursive call takes us just one step closer to the base case.
Classic base case plus recursive case format:
const loop = (n) => {
if (n === 0) {
return;
} else {
console.log('hello');
loop(n - 1);
}
};
Logs 'hello'
n times.
const loop = (n) => {
if (n !== 0) {
console.log('hello');
loop(n - 1);
}
};
Same behavior as before.
const loop = (n) => {
while (n !== 0) {
console.log('hello');
n--;
}
};
Another way of doing something n times.
We count by adding one.
For instance: 5 + 3
Start at 5 and count, i.e. add 1, three times.
5 … 6, 7, 8.
5 + 3 = 8
const add = (a, b) => {
if (b === 0) {
return a; // No more to count
} else {
// Recursive call will count from the same
// starting number but will count one fewer
// times since we've added the one in.
return 1 + add(a, b - 1);
}
}
I.e. we are adding 1
b times.
add
add(3, 2)
1 + add(3, 1)
1 + 1 + add(3, 0)
1 + 1 + 3
1 + 4
5
Multiplication is repeated addition.
Doubling is repeated multiplication by 2.
Tripling is repeated multiplication by 3.
Power (exponentiation) is repeated multiplication.
The basic structure of array recursion looks like this:
const r = (array) => {
if (array.length === 0) {
return BASE_CASE_VALUE;
} else {
return COMBINE(array[0], r(array.slice(1)));
}
}
Base case is almost always the empty array.
Combination is almost always of the first element of the array with the result of recursing on the rest of the array.
slice !== splice
Note that Javascript arrays support two methods slice
and splice
.
Unfortunately they do slightly different things and if you use splice
when you meant slice
, you will probably break your program or at least confuse yourself.
(splice
modifies the array while slice
does not.)
Add the numbers in an array.
const sum = (numbers) => {
if (numbers.length === 0) {
return 0; // the sum of no numbers is zero
} else {
// combine by adding
return numbers[0] + sum(numbers.slice(1));
}
}
Multiply the numbers in an array.
const product = (numbers) => {
if (numbers.length === 0) {
return 1; // the product of no numbers is one
} else {
// combine by multiplying
return numbers[0] * product(numbers.slice(1));
}
}
const search = (array, thing) => {
if (array.length === 0) {
return false; // thing is definitely not in empty array
} else {
// Combine by or'ing. Also have to make a
// boolean out of the first element.
return array[0] === thing || search(array.slice(1));
}
}
const treeMap = (tree, fn) => {
if (isLeaf(tree)) {
return fn(tree);
} else {
return {
left: treeMap(tree.left, fn),
right: treeMap(tree.right, fn)
};
}
};
Base case is when we reach a leaf of the tree.
Recursive case will recurse down each branch and then combine the results somehow.
Note that this is more complicated than a simple loop.