Recurse (n.

): To Curse Again **************************** Functional programming languages have good support for recursion, because they depend on it for looping. And if you are doing pure functional programming, you will have absolutely no way to iterate or loop without a recursion. This is good and bad. Mostly good, because recursion, once you start doing it, becomes the clearest way to write any repetitive algorithm. You use loops in languages like C (imperative/impure languages). That is good for the machine, but bad for the programmer. C looping is only an inch ahead of the assembly version. So, let's finish this here and now: looping is not good for programmers. Looping is good for the machine (efficient) but not for programmers (destructive, impure, not backtrackable, impairs equational reasoning _severely_). It's up to you to choose ye this day what ye shall do - code for the machine, or code for yourself. Right now, your processor is mostly idle. Probably nearly 95% idle. But your eyes aren't. You have only two, you know. Either you're coding or reading this. So you're not coding. That means you should maximise time-saving, rather than processor-saving. Optimise for programmer time - that's the _only_ reason why we are not using the ENIAC* anymore. Also why you probably shouldn't be reading this. :o) Recursion is hard to start out for _everyone_. Don't believe that crap of being wired for it or not. Believe me, loops are harder to master than recursion. And if you have a language that has pattern-matching (especially like Haskell-style match declarations), your code becomes way, way shorter, much, much clearer, and far, far more elegant. Loops are bad. Recursion is good. But ... But recursion is not well-supported in mainstream programming languages. That is a most-important issue, because you aren't paid to do what you like. You are paid to kick code in mainstream languages. Work is work. Consider the following cases. In Python, this is an elegant way to write a length function. def length(x): if not x: return 0 else: return 1 + length(x[1:]) It can even get more elegance. Check the more-functional version. def length(x): return x and (1 + length(x[1:])) or 0 So ... >>> length([]) 0 >>> length(range(0, 10)) 10 >>> length(range(1000) [***ERROR***] Python, by default, doesn't allow more than 1,000 recursions. You can change the

limit, but that ceases to be portable. The standard len function isn't recursive, so it works. And much faster. Yes, recursion is slow in Python. Much slower than the looping equivalents. I guess it is inherent to unoptimised recursion to be slow, anyway. In many compilers, tail-call optimisation - in fact, recursion optimisation in general - is ignored. It is an after-thought even where it is later tacked on. Because, you see, it is a subliminal message: `Use loops.' That's bad brain-wash, though. Okay, consider these two examples of a function that's supposed to flatten a Python array. def flatten(arr): if not arr: return fst = arr[0] if type(fst) return else: return >>> [1, >>> [1, >>> [1, flatten([1, 2, 3, 4] flatten([1, 2, 3, 4, 5, flatten([1, 2, 3, 4, 3,

arr != type(arr): [fst] + flatten(arr[1:]) flatten(fst) + flatten(arr[1:])

2, 3, 4]) 2, 3, [4, 5, 6]]) 6] [2, [3], 4], 3, [4, 5, 6]]) 4, 5, 6]

I challenge you to re-write that without recursion. If you manage (hot hacker that you are), then proceed to count the lines. You may say that this problem is inherently-recursive. Well ... Here's the news: every iterative problem is inherently-recursive. The moment you emancipate yourself from the mental slavery to loops, you will see this point and come crying `Why didn't anybody tell me this before?' When you can avoid it, don't use loops - recurse. In functional programming languages, a function is _one_ single expression. Python favours imperative programming, and so one ends up writing many statements. That above problem, in a more-functional language, would have been one single statement. Ruby has a surprising affinity for functional programming, even insisting on pure defaults and marking the impure! See the same flatten function (which comes standard in the Array class). def flatten(arr) if arr.any? then (arr[0].class == Array ? flatten(arr[0]) : [arr[0]]) + flatten(arr[1, arr.length]) else [] end end Whole powerful function, one single tight expression. This kind of thing could happen in every fourth line of code you write (and you'd have 75% less code to write), but your language isn't letting your mind run free. And this kind of challenge shows up in dynamic tree structures like file systems, code indentation levels, nestable data structures (as above), regular expressions, code expressions, and the like. Of course the above function is quite intense, in that there is a lot of logic in one single expression (unlike, a single expression in the standard loop, say, ++i). It is called `dense code'. That is common (indeed it is all you find, often

with even more density and intensity) when you code in a language like Haskell. But then, someone said Haskell is one of those languages where you do more thinking than typing. These days, programming is more of a typing challenge, to test the dexterity of the finger you use to press SHIFT, rather than a mental affair. Such elevated programming replenishes the delicate factor that got you into programming in the first place. So use recursion, shun loops. From the classic Why Functional Programming Matters**: `The only faintly plausible reason one can suggest on the basis of these advantages is that conventional programs consist of 90% assignment statements, and in functional programs these can be omitted!' Loops are driven by assignments. When you recurse, you generally eliminate assignments. Choosing recursion immediately throws away 90% of the code redundancy in your iterations. You're a programmer, not a typist. Wise up. There is a nice thing about recursion (instead of looping) especially in languages that don't have good support for it. In an algorithm that will have an n that is reasonably assured not to cause a stack overflow, you should can use recursion in testing, so that in case of a deadlock or an infinite loop, you will get a stack overflow to point out the problem with sufficient accuracy, where loops would have sat there being unresponsive. In closing, just say no to the unthinking loyalty to loops that abounds today. You may, in so doing, have to outgrow your current programming language, or stay with it (since work is work) but with a recursion reflex that will make your programs in general more elegant. Recursion only has efficiency problems, because of the segregation it is facing among runtime and compiler implementers. But it yields more for you, the programmer. If it performs too badly, swicth compilers/runtimes or throw more silicon at it. In the end, you are coding so you can have elevated fun and still have time to play with the kitten, read XKCD, make that call, read this propaganda, do a community service, learn a new language, sleep, or make love, not to spend your priceless fingers for an inanimate sequence of boring instructions. * ENIAC - ** -LeCamarade