You will eventually learn about something called "for loop", and it will be nice.
You will eventually learn about something called "for loop", and it will be nice.
Indeed, this is why everyone knows the J programming language.
fold sum 0 collection
versus acc = 0
for x in collection:
acc = acc + x
or the even worse int acc = 0;
for(int x = 0; x < collection.length; ++x) {
acc += collection[x];
}
You can read one line and know exactly what's happening in the fold example. In the Python and C++ examples, you have to scan more lines and there's way more opportunity for typos.A for loop gives you better memory management and speed, but the tradeoff only makes sense to me if you're doing embedded work or something. Otherwise, eat the .000000000001% speed loss to reduce the risk of logic errors, typos, etc. and to improve developer ergonomics.
Adding numbers like this is not common in real world code. Now let's say instead of adding x, you have too look up X in a cache with an additional "type" param and update a metric of cache hits (or misses). You have to define a free function to keep your fold readable and understandable. In for loop it's much easier to understand.
I agree. But you'd do that for a for-loop, too, unless you want a bloated for-loop.
> In for-loop it's much easier to understand.
I have to disagree there. You'd still be working with a free function, or you'd be working with a bloated for-loop body.
Combining cache loopkups, metric tracking, etc. runs into SOC issues that IME for-loops just let imperative developers get away with until it comes time to test their code.
Furthermore, free functions aren't bad. They're good. They're a self-documenting abstraction. Unless you name it `function_one` or something.
Having my fold lambda do its primary business role but call `update_cache_and_metrics` makes it unnecessary for someone reading the flow of logic from even needing to go read the body of that free function.
Plus it forces you out of whatever lazy/streaming paradigm you had going on. If your foldr produces a list, downstream can start consuming it in constant memory as long as you let it do its thing.
I.e. there is no initial value to pass in, but the result is an Optional to handle the empty iterator case. That’s how rust does it, for example:
https://doc.rust-lang.org/std/iter/trait.Iterator.html#metho...