tldr; reimplement standard library functions in your favorite language without loops.
Background
For a few years after college I spent a lot of free time doing projects in Standard ML and Scheme. As a result I got really comfortable doing recursion. The two big reasons for this are 1) neither Standard ML or Scheme have loops and 2) they both have very small standard libraries. (Ok, they have loops. They're just so limited as to be useless.)
I ended up building a standard library for Standard ML including string functions (contains, indexOf, count, replace, etc.), an HTTP server and client, a hash table, a binary search tree, parts of a Standard ML parser, and so on.
All of this without loops.
Strategy
The good news (if you don't want to learn a new language) is that you don't have to take up Standard ML or Scheme to get better at recursion. But you do need to dedicate some time to practicing recursion to get better at it.
My recommendation would be to pick 10-20 string or array functions out of your favorite language's standard library and reimplement them without loops. (Obviously, start simple and just pick one. But don't stop there.)
Some examples
Here's an example reimplementation of indexOf
in
JavaScript:
function indexOf(input, toMatch) {
function helper(index, offset, test) {
if (index === input.length) {
return -1;
}
if (toMatch === test) {
return index;
}
if (input[index+offset] !== toMatch[offset] || test.length > toMatch.length) {
return helper(index+1, 0, "");
}
return helper(index, offset+1, test+input[index+offset]);
}
return helper(0, 0, "");
}
Or here's an example immutable reimplementation of insert
in Python:
def insert(arr, index, item):
def helper(currentIndex, accum):
if currentIndex == len(arr):
return accum
if currentIndex < index:
return helper(currentIndex+1, accum + [arr[currentIndex]])
if currentIndex == index:
return helper(currentIndex+1, accum + [item, arr[currentIndex]])
return helper(currentIndex+1, accum + [arr[currentIndex]])
return helper(0, [])
You're going to find an edge case and that's alright. The important part at the moment is practicing recursion.
For bonus points, avoid all mutation in your implementations and use only tail recursion.
Happy recursion!
Reimplementing standard library functions without for loops is a great way to get better at recursion and you don't need to use a functional programming language to do sohttps://t.co/JiPnXMQW3l pic.twitter.com/MHwX5t70HT
— Phil Eaton (@phil_eaton) March 7, 2021