In numbered-lines code you can’t see the start of a goto loop. In labeled-lines code it’s not that hard to infer that it is a jump target, but having a condition/iterator in one place is an obvious benefit.
That said, I believe most people who “boo GOTO” never actually used it to make sense of what could be wrong with it and how it feels really.
Anyway, I think that this analogy(?) is confusing and makes no sense.
Conceptually, the `map` function is just syntactic sugar for `for` loops, and it's also meant to simplify actions. There are functional equivalents to many small patterns of code that occur often - for instance
lst = []
for element in range(10):
lst.append(element * 2)
Is a very common pattern, that can be expressed with less typing (and less mental overhead, when you become used to it) by
lst = list(map(lambda x: x * 2, range(10)))
Similarly, another very common mini-pattern is
total = 0
for el in range(10):
total += 3 * el
Which can be more swiftly expressed by
total = reduce(lambda acc, el: acc + 3 * el, range(10))
These examples are trivial, but once you start using these higher level syntactic sugar-like constructs, you often find that code tends to fit together more nicely and in ways that make more sense, even if only because you used a filter operation before the map instead of writing another level of nested `if` statements inside a loop body. Code gets easier to follow, not unlike how it's easier to reason about the behavior of a `for` loop than it is to keep a bunch of `goto`s in your mental model of what the code does while at the same time thinking about whether the business logic part of it makes sense.
Tbh, I get your imperative examples instantly but my mind struggles to autograsp these multilevel functional parts like list(map(lambda. Too much noise, I have to think through it to get it.
I’d prefer a loop with ifs and continues/breaks.
It may be a lack of experience or habit, but then I can write code like that (and worse), and it doesn’t make any sense to me. Don’t get me wrong, not that I refuse to use maps or filters or folds, but not that I want to make a whole program of them either. They have their place where factoring-out a block of code feels stupid, but if I had something like:
[1, 2, for (x of xs) {
if (cond) {emit x}
}]
I’d never bother with these function-al things. It’s not FP that is rich, it’s a traditional imperative syntax that sucks. Paradigm shift is not equal to usage out of [in]convenience.
> Tbh, I get your imperative examples instantly but my mind struggles to autograsp these multilevel functional parts like list(map(lambda. Too much noise, I have to think through it to get it.
That's exactly why most FP languages have pipe operator, so it's incredibly easy to read.
lst = range(10)
| map(fn x -> x * 2 end)
| map(etc...)
That doesn’t change much for my read ability. It even reads more imperatively, like: I take a range of 0 to 10, map it over x * 2, map it over… What do I get? A mapping? Maybe?
Meanwhile, a for loop is straightforward, you go from 0 to 10 and append a double or add a triple of x to an accumulator. I appended/added them, that’s what I get. It’s like my brain somehow follows {} scopes and understands their local envs with no effort.
If this syntactic style works for you without this friction, nice. But it doesn’t work for everyone and I suspect that this FP/PP is biased by this effect at both sides.
A mapped list/enumerable it was originally given. You don't think what you get when you add two numbers, don't you? Language just works certain way. Not understanding a simple building block of a language isn't a valid argument against it. All you essentially say is that you got so used to OOP concepts that anything else is hard to read. And it's ok, it's the same way for everyone... But it's not a valid argument to say that "fUnCtIoNAL bAd". The whole thing here boils down to what you already said - lack of experience.
My honest advice is - try to learn one functional language, like honestly learn and understand it, try writing something with it. It really does expand horizons.
> I can write code like that (and worse), and it doesn’t make any sense to me
I'm learning FP and I see value with writing code with map, reduce etc as those are expressions instead of statements. Expressions guarantee you have a result of particular type (with possible side effects if you prefer), but statements DO side effects. The loop may or may not insert some value into resulting list because some branching happened or you forgot some else condition, with map you guarantee you get same number of objects of particular type back.
Plus that enables composition (like in C# LINQ) - by not extending some loop with different kind of responsibilities but just passing result to next function that modifies/filters the result.
It results into [1, 2, …(some xs satisfying cond)]. Emit does just that - emit another value into a context where for-expr was used. It emits some of x-es into that array literal.