3 ms·
> Some Rust programmers, when faced with performing operations on a sum type (like Result) or container, tend to reach for point-free map-filter-reduce code stu
by epage 4y ago
> Some Rust programmers, when faced with performing operations on a sum type (like Result) or container, tend to reach for point-free map-filter-reduce code stuffed with higher-order functions, lambdas, trait generics, and return type inference, requiring looking up the documentation or implementation of multiple helper microfunctions, and asking the compiler for the inferred return type. My preference is usually to write imperative code matching over objects or looping over iterators, except in cases like "minimum of list" where the loss of clarity of a loop exceeds the loss of clarity of a reduce() method call.
I know for myself, I overdid it at times as I was learning the trade offs.
Where I've currently settled is simple map/filter operations to tweak things into a more readable state are better than the more procedural approach. Also keep to simpler combinators (e.g. no `map_or` / `map_or_else`). If things become too complicated, be procedural. If there are side effects, be procedural.
Another way I have for framing it is the code layout (files, functions, blank lines, newlines, indentation) should be used to highlight the business logic. Early returns, `?`, post-fix combinators, etc should be used to reduce boilerplate that detracts from the business logic.
- nextaccountic 4y ago> If there are side effects, be procedural. Yep! That's why Iterator::for_each https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.for_each https://doc.rust-lang.org/stable/std/iter/trait.Iterator.htm... is more often than not a code smell [0]; it exists mostly for the sake of writing side effects in functional style. So something like something.map(|x| ..).for_each(|x| do_something(x)); Should probably be written let iter = something.map(|x| ..); for x in iter { do_something(x); } It's still okay to use Iterator::map and other iterator combinators, but using for instead of for_each here is probably easier to read. [0] One exception is in the documentation "In some cases for_each may also be faster than a loop, because it will use internal iteration on adapters like Chain."