Are captured variables of a closures a 'noun' or a 'verb'? In the end they are equivalent, it's the same thing - state by another name.
And recursions are no fun, when you run out of stack space.
Are captured variables of a closures a 'noun' or a 'verb'? In the end they are equivalent, it's the same thing - state by another name.
And recursions are no fun, when you run out of stack space.
A function on the other hand forces one to think of function calls and not some kind of state that was set earlier, splitting time in parts of before setting that state on an object and after. A function (when using the term more strictly) will always give the same result for the same input. I get more guarantees about my program than I get when classes and instances of them are mutated.
Recursion can solve problems very elegantly at times. When I use it in other non-TCO languages, I always think about stack depth and consider externalizing the stack as an option.
One thing mathematical, that I understood much better through SICP was hiw Church numerals work and how they could serve as numbers in theory. Another one was derivatives, since one writes a symbolic calculation of derivatives in SICP. Then the Newton method for finding zeroes. Basically any such topic, that one needs to implement in the exercises of SICP, because one has to get familiar with how it works more, in order to implement it.
https://github.com/MoserMichael/jscriptparse - this is my pet project, it's an educational / shell scripting language. It tries to allow for concise expression, and you have a REPL/shell.
Ideally I want to fit this niche as well, where you can solve these problems in a concise manner (well, maybe slightly more concise than python or javascript, and with a subset of the features that you would expect with a programming language for grown ups)
Here is the tutorial: https://github.com/MoserMichael/jscriptparse/blob/main/PYXTU...
f a -> b -> c
you get three steps until all information is known and computation can happen
you didn't have to define anything, didn't have to think about it, while in OOP you'd have
class F:
setA
setB
setC
logicThatCanBeCalledAnytime
here you either get a random logic with unknown a,b,c stateor to think very carefully what states things should be
or design safeguards around every methods to ensure things are known... (and AFAIK no mainstream OO language even makes an attempt at having metalevel state transition checks easy to define and ensure..)
9th circle of dante
Once you've gotten used to being able to use recursion, stack depth limits seem as lame as olden-days limits on string length (255 characters was common in Pascal).
Javascript is a frustrating case where unlimited recursion is technically possible in modern engines, but they still often limit it to 10000 or something.
Python limits it arbitrarily, just to force you to use its fancy iteration system.
Python has an arbitrary and low default limit because it isn’t optimized (because stack traces are considered important), abd call depth is an effifiency issue that risks blowing up without a limim because of stack depth, and failing fast in the likely-erroneous case of deep call stack given all that is just sensible. Python also. Lets you alter the limit at runtime; ita a soft, not hard, limit. The hard limit is stack space.
Python's "solution" requires changing a global, which is an ugly thing for a library that wants to recurse to do.
There’s trampolines in almost any programming language to implement recursion if necessary, and python has itertools to build what Scheme calls streams, for arbitrary computation.
Compilers and interpreters can (more easily) optimize tail-recursive algorithms to avoid the normal cost of creating a new stack frame and making a normal function call, which means the recursive algorithm has performance more like that of an iterative implementation.
https://en.wikipedia.org/wiki/Tail_call
https://llvm.org/docs/CodeGenerator.html#tail-call-optimizat...
Now Python doesn't do tail call optimization out of the box (surprise). but there is a module that is adding some magical decorator that fixes that: https://pypi.org/project/tail-recursive/
(actually need to look how they implement this decorator, it must be some serious hack.)
If you can only optimise calls to yourself, you have a very limited form of tail call optimisation. It's an important point in the context of Scheme, where they made a big deal out of experimenting with continuation passing style. In CPS, all function calls are tail calls, and you want to optimise them all, even though most are not recursive.
Eliminating recursion might be difficult to detect if multiple functions form a mutually-recursive set, or if data structures have to be introduced to compensate for no stack (e.g., converting a depth-first search from recursive to iterative form requires a stack).