5 ms·
It’s also because it’s good practice to use the lowest power loop possible. A for loop can implement a reduce, a reduce can implement a map, a map can implemen
by mrcartmenez 6y ago
It’s also because it’s good practice to use the lowest power loop possible.
A for loop can implement a reduce, a reduce can implement a map, a map can implement a forEach, but not the inverse.
- thaumasiotes 6y agoHuh? I don't follow. In [1]: def lred(function, iterable, initializer): ...: acc = initializer ...: def reductor(el): ...: nonlocal acc ...: acc = function(acc, el) ...: for n in map(reductor, iterable): pass ...: return acc ...: In [2]: lred(lambda a,b: 10*a + b, [2,4,6,3,1], 40) Out[2]: 4024631 What's stopping you from running these equivalencies in either direction?
- jessedhillon 6y agoThey mean that the forEach runs code per element, but cannot return a transformed list of values, you need map for that. A map can run code per list element but the result must be injective (one-to-one). Reduce can do all of the above, but must return a lower dimension result from its input. And finally, a for loop is basically omnipotent.
- DangitBobby 6y ago> Reduce can do all of the above, but must return a lower dimension result from its input. What do you mean by this? You can accumulate just about anything into the resulting object, including a copy of the original array.
- SamBam 6y agoI think it's just being confusingly stated. GP already said that reduce could implement map. I think it's merely that reduce can just output a single result, of any type. (Which is already more powerful than map, which must output an array.) Of course, in fact you could hack anything in any of these, since you could be doing other work in the function called. But I think the general principle is sound.
- thaumasiotes 6y ago> (Which is already more powerful than map, which must output an array.) Don't tell Common Lisp.
- eru 6y agoEspecially, a for-loop can break out early or skip elements.
- thaumasiotes 6y agoSo can reduce. You'd put that logic in the function you pass to the call to reduce. So can map. Ditto. So can foreach. Ditto again. for el in values: if el == 3: pass else: do_something_with( el )
- mekkkkkk 6y agoNo, that's just a guard condition. Parent post was referring to break, i.e. skip the rest of the iteration.
- thaumasiotes 6y agoFor forEach that's easy: for el in values: if el == 3: return do_something_with( el ) For the other two, you still can, but you'll need to handle the control flow yourself, by doing something like goto or invoking a continuation.
- mekkkkkk 6y agoThat's a for loop. And depending on the language I'm pretty sure that return call would exit the parent scope.
- thaumasiotes 6y ago> That's a for loop. I take it you've never read any Python? That's a forEach. Python doesn't even have a for loop construct (though it does have while, which is equivalent). > And depending on the language I'm pretty sure that return call would exit the parent scope. Yes, that's the point, that's an illustration of terminating the forEach before you've processed each element.
- jolux 6y agoforEach is actually more powerful than map, you would not be able to use map for side effects in a static and/or lazy language. In a strict, dynamic language, it matters less. Even so I wouldn't describe being an expression vs statement as a difference in power. It's contextual.
- thaumasiotes 6y ago> forEach is actually more powerful than map, you would not be able to use map for side effects in a static and/or lazy language. You might notice this problem above, where it's necessary to do for n in map(reductor, iterable): pass to realize the mapping.
- thaumasiotes 6y agoA forEach can easily return a transformed list of values. acc = [] for el in values: acc.append(f(el)) return acc This hierarchy doesn't exist; you can pretty much implement any of them in terms of the others. To make that untrue, you need to define very strict limits on what else your language can do. (Sure, we produce a transformed list here through the use of side effects. But note that the original example sparking the claim that forEach can't do what map can was this: .forEach(() => button.click()) Side effects are clearly allowed.)
- joe-user 6y agoThe forEach isn't returning it in your example, the line after it is returning. Try again without acc and I believe that's what was meant. You can implement any of them in terms of the others, but only if you break convention and introduce side effects. Follow convention and try to implement (for example) reduce with map and you'll find that it's not possible.
- thaumasiotes 6y ago> You can implement any of them in terms of the others, but only if you break convention and introduce side effects. This can't be right. forEach has no effects other than side effects. A convention that says not to use side effects prevents you from using forEach at all. But that would make claims about the place of forEach in a hierarchy into meaningless nonsense. > The forEach isn't returning it in your example, the line after it is returning. That depends on your point of view. C has numerous functions which accept pointer parameters and return values in those parameters. That's just the normal way to return multiple values in C. And by that standard, the forEach itself is returning the transformed list; that's where the transformation occurs. The following `return` line is only necessary if this is a snippet within a function whose purpose is to execute a for statement; you would actually do this inline, by just writing the for statement without needing a following `return`.
- HeavyStorm 6y agoI really don't think you got the original point...