5 ms·
I think replacing common usage patterns of generic control structures with named constructs adds clarity: for(blah blah blah) tells the reader nothing mor
by Zak 10y ago
I think replacing common usage patterns of generic control structures with named constructs adds clarity:
for(blah blah blah)
tells the reader nothing more than there's going to be a loop, but
map(blah blah blah)
tells the reader one sequence is going to be transformed into another by applying a function to each item. That's more informative to the reader if used for its intended purpose. It has the opposite effect if abused to repeatedly call a function mainly for its side-effects.
All programming techniques should be viewed as means to write code that's some combination of readable, reliable and performant, not as ends themselves.
- jghn 10y agoRight. I find that the easiest code to read is code written in a data flow style such that it's a series of transforms on data.
- mercer 10y agoI'm not a functional purist, but I find that the functional 'principles' that I benefit the most from, in any context, are 1) massaging my data into the right shape with as few transforms as possible/practical/legible, 2) using pure functions whenever possible (in practice this often means accepting a few extra parameters in lieu of writing the code as a method; avoid 'this' in js, for example), and 3) starting with the data structures and seeing my app as, to a large degree, just a set of transformations on that (which usually is appropriate for the type of stuff I build). I don't use partial application/currying that much, but more and more over time. All in all I feel that doing these things have greatly improved my code and efficiency, and I'm kind of waiting for some downtime to get back into learning the more 'hardcore' functional languages.
- jghn 10y agoThat's about where I am. I like the idea of being a purist and see the potential gains but practical reasons such as needing to deal with other humans as well as my own lack of intelligence keeps it to this sort of midrange level
- mannykannot 10y agoI don't think the 'map' is actually telling us anything very different than the 'for'. It is an issue I have with most articles in this vein, and this one is no different: they give simple, obvious examples that do not suggest that there is much practical difference between the approaches. We could do with some articles in which the examples are sufficiently well-developed that the advantages are clearly non-trivial. It might be said that any such example would be too complex and drawn-out for an article like this, but if so, then to me that is like the drunk looking for his keys under the lamp-post: writing an article that claims a simple example shows a profound difference, when it does not, suggests that the Emperor's wardrobe is threadbare. The thing to do is to provide links to articles where this is worked out in sufficient depth, and I would like to see some of those links here.
- mercer 10y agoEven though I share your concern, at least in my own code 'map' usually does tell me things that 'for' doesn't. Because if I were filtering a list, I'd use filter or reduce, if I were picking an element from a list I'd use pluck or whatnot, etc. So seeing a 'map' means that 99% of the time I'm transforming one set of values into another set without removing or adding elements.
- village-idiot 10y agoSure it does. For can be used for any of the following. * Mapping (producing a data structure of the same size/type) * Filtering (producing a data structure of the same type buy smaller) * Side effects * Collecting (producing a different data structure) If you're incredibly unlucky or foolish a for loop might be doing more than one operation at a time! Assuming you're only using the return types, map, filter, and collect are very clear about having only one purpose. If that's not telling you more I don't know what is.
- deleted 10y ago[deleted]
- mannykannot 10y agoThat's a fair point about map being constrained in the top-level structure of what it returns, but what map actually does depends on the function that is being mapped, and includes the possibility of more than one operation at a time - and if your language allows side-effects it can do that too. The point is that you have to look at the 'blah, blah, blah' to know what is happening (actually, the point of my original post is about extravagant claims of what simple examples demonstrate...)
- mpweiher 10y ago> map() tells the reader one sequence is going to be transformed... Except in this case it wasn't actually a sequence, but an Optional/Either and it wasn't about transforming that sequence but about error handling. So in a way the code wasn't even not intention-revealing, it was actually deceptive.
- chc 10y agoNo, those functions were transforming the wrapped value. If there were no need to transform anything, you wouldn't need map or flatMap.
- mpweiher 10y agoNot sure what the "No" is about, because the rest is a restatement of what I wrote. Yes, they are transforming the value that's wrapped in an Either/Optional, just as I wrote, and yes, the map/flatMap is necessary due to that construction. However, just as I also wrote, that's not an actual sequence of values, it's a single wrapped value (or none).
- appsappsapps 10y agoThe "no" was probably aimed at the fact that you were splitting hairs against their use of "sequence". Optional can generally be thought of as a "sequence" of one or zero values. You could use an array of "[some]" or "[] /* none */" to manage control flow in an almost identical way (you'd just be adopting and managing an API that doesn't statically ensure that these arrays never have more than 1 value). "map/flatMap" are predictable functions that can be used to manage the transformation of data (which is generally the entire point of code). The type/context that a computation is lifted into communicates a lot: Optional, for example, can be returned for a computation that may or may not return a value, and it can be "mapped" into another value by a pure computation that _always_ returns a value, or "flat-mapped" through a computation that may produce another nullable value. Anyone familiar with these basic functions can jump in, read the code, and generally know that every computation lifted into "map" can't fail, while every computation that is "flat-mapped" can. And in static languages it's all checked by the type system! No testing for "null" everywhere!