3 ms·
> I've also never found the Lisp (and many other FPs) emphasis on recursion all that compelling. Recursion appeals to me because of immutability: I do not wan
by mrkeen 3y ago
> I've also never found the Lisp (and many other FPs) emphasis on recursion all that compelling.
Recursion appeals to me because of immutability:
I do not want to do a summation by writing the wrong answer to memory, and then updating it in-place until it's the right answer. It makes me have to think not only about what the right answer is, but when it is.
But can't I just use stack variables? Well, I don't think summation of primitive ints using stack variables is too taxing, but what about computing a word-count instead of a summation? Then your 'stack variables' are pointers into Strings and mutable HashMaps. When you return the result, do you make a defensive copy? How deeply do you copy? Your clone of a HashMap can still reference mutable data in your original HashMap.
Do you name your variable 'result' when it does not yet contain the result?
You might have to think about the primitive/object split - when is it pass-by-value and when is it pass-by-pointer? Do you have in-values and out-values? With immutability, you only have values, and you only pass-by-value.
If you're sharing objects across threads, and you decide to lock - is that sufficient? What if the caller takes the lock, does a get(), releases the lock, and then starts mutating the gotten value, bypassing the protection of the lock. Now you're thinking about defensive copies and maybe deadlocks too. Just share an immutable value without a lock.
Sometimes recursion is aesthetically better, but usually it's just what you're left with after you take a big hammer to mutability and its surrounding issues.
And most of the time (in Haskell but I'm guessing in Lisps too) you don't write out direct recursions, but instead use maps and folds which have recursion under the hood.
- galaxyLogic 3y agoI think mutable variables (inside functions) are just fine, as long as the function itself always returns the same result for the same arguments. That is the essence of "pure" I think. A function should be a "black box". I don't care what happens inside it as long its externally observable behavior is pure.
- cmrdporcupine 3y agoHere's what I don't like about recursion & associated world of linked lists car/cdr: Modern Computing Hardware performance characteristics. That is, missed branch predictions, and lost opportunity to apply SIMD/vector operations. On "classical" computing hardware, it's fine. On present-day architectures we're better off writing with "wider" operations across vectors rather than depth-first-ish recursive operations on scalars. But yes, for some domains, the performance doesn't matter. I just also find recursion more difficult to read in some contexts. In others, things like tree transformation etc. it's easier to read, for sure. But I am also a fan of immutable, or at least copy-on-write, data, expressed in series of functional applications, etc. etc.
- chriswarbo 3y agoMost of the time "recursing through a linked list" is still too low-level; and we can instead write our code at a higher level with `map`, `reduce`, etc. Recursion is then just an implementation detail of those functions; which we could instead swap out for, say, massively parallel fan-out across a datacentre (i.e. frameworks like MapReduce, and its descendents like Spark)!