4 ms·
I find that decomposing iteration into map and filter expressions typically clarifies my understanding of the problem and makes the resulting code more general
by jolux 5y ago
I find that decomposing iteration into map and filter expressions typically clarifies my understanding of the problem and makes the resulting code more general too, and I just disagree that for-loops are clearer. Combining a map and filter into one loop body tends to create specific, imperative code that doesn’t need to be specific or imperative. For one, loops require mutation to have the same effect as filter and map, and as soon as you’re maintaining state, things get confusing. My usage of higher order functions instead of for-loops is an expression of my belief that programmers should always use the least powerful construct they can to solve a problem.
In general though I think the functions used in map and filter should be total. Most languages are not expressive enough to handle errors fluidly in long chains like that, you can do it with monads but apparently everyone hates those except me.
- throwaway894345 5y ago> I find that decomposing iteration into map and filter expressions typically clarifies my understanding of the problem and makes the resulting code more general too, and I just disagree that for-loops are clearer. Agree to disagree I guess. > Combining a map and filter into one loop body tends to create specific, imperative code that doesn’t need to be specific or imperative. For one, loops require mutation to have the same effect as filter and map, and as soon as you’re maintaining state, things get confusing. I agree that immutable, declarative code is easier to reason about in general than mutable, imperative code, but it's not a binary proposition. I posit the cost of managing the tiny bit of very-local mutable state for a for loop is a lower cost than trying to model a problem in terms of map and filter. While I can appreciate the elegance in "immutable always", I think it's too puritanical for real world software development, especially in these cases which are simply expressed as for loops. Note that languages like Python have strong support for immutable expressions and `for` loops, and it seems very common (even idiomatic) to use imperative `for` loops for anything more complicated than the simplest list comprehensions. > In general though I think the functions used in map and filter should be total. Most languages are not expressive enough to handle errors fluidly in long chains like that, you can do it with monads but apparently everyone hates those except me. I think it's just that monads tend to allow for very abstract code at the expense of understandability, and the abstraction that monads facilitate is often well in excess of what a given problem requires. If you're writing code to maximize abstraction (which is a lot of fun), monads (and map/filter/etc) are great, but if you're trying to work with a team to build software to solve real problems, you probably care a lot more about readability than gratuitous abstraction and the monad (/map/filter/reduce/etc) juice frequently isn't worth the squeeze.
- jolux 5y agoPython’s FP capabilities are severely constrained by not supporting multi-line lambdas or composition operators (pipe, sequence, etc). It is not a good language for functional programming at all. The community norms explicitly push you away from using FP in it because of how limited it is. We use it for wrangling large data sets and tend to hate every minute of it. My workplace uses Elixir exclusively in production for our backend services, so we’re all functional programmers and we do not find that map, filter, and reduce make things harder to read, quite the opposite. Breaking up loops does not introduce cognitive overhead, it makes every step in the chain more explicit. You can call this personal preference but there’s nothing concrete in your belief that for-loops are more readable or easier for teams of programmers to maintain, many people disagree.
- iudqnolq 5y agoI generally agree with you, but it's nice that in Rust you can use a for loop if it makes more sense. I mostly end up doing this when I want to reduce to multiple collections (put type a in here, type b in there) or call functions that return different types of errors. The other time it's very useful is when translating algorithms specified in an imperative form. I translated a bunch of algorithms specified as for loops to elixir, and it was annoying to have an extra source of complexity when comparing the implementations for correctness.
- jolux 5y agoIt’s definitely nice to have the imperative constructs but spending a lot of time with pure languages has changed my perspective on mutability. I think Rust mostly fits it, data is immutable by default in Rust.
- throwaway894345 5y ago> Python’s FP capabilities are severely constrained by not supporting multi-line lambdas or composition operators (pipe, sequence, etc) Hardly. You can absolutely have multi-line lambdas, just not multi-expression lambdas (the real limitation is that there are no try/except expressions so certain fallible manipulations aren't so easily expressed). Similarly, Python lets you overload operators so you could always override `|` or whatever. Of course, operators are just syntax sugar for function calls so this strikes me as a cop-out. In either case, neither of these excuses are pertinent to the community's rejection of complex comprehensions or higher order functions. > My workplace uses Elixir exclusively in production for our backend services, so we’re all functional programmers and we do not find that map, filter, and reduce make things harder to read, quite the opposite. Breaking up loops does not introduce cognitive overhead, it makes every step in the chain more explicit. You can call this personal preference but there’s nothing concrete in your belief that for-loops are more readable or easier for teams of programmers to maintain, many people disagree. You could argue that any two models which evaluate to the same thing are fundamentally equally easy to understand. You could argue that monads are just as easy to understand as a sequence of statements in an imperative language, but experience suggests that people have a harder time understanding the more abstract concept rather than the more concrete concept. This shows up all over--Newtonian physics are more easily understood than the more abstract quantum physics and in mathematics "more advanced" math tends to mean roughly "more abstract".
- arethuza 5y agoI really like the method style of LINQ in C# - which I would agree are much clearer than the equivalent explicit loops.