Simply using map and folds instead of for-loops is just more stupid shit that doesn't really help your code at all. It's not really any shorter or less bug-prone, and it makes your code harder to follow for people who don't understand map & fold.
The real benefit comes from when you understand the concepts behind map and fold. If you realize that fold is nothing but replacing each n-ary constructor of an algebraic data type with an n-ary function, then you recognize that you can do the same thing for data structures besides sequences, like binary trees, graphs, and ASTs. There you're getting some benefit, because there's no built-in language syntax for iterating over those.
data List a = a : [a] | []
[1, 2, 3, 4] = (1 : (2 : (3 : (4 : []))))
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr (+) 0 [1, 2, 3, 4] = (1 + (2 + (3 + (4 + 0))))
foldr (*) 1 [1, 2, 3, 4] = (1 * (2 * (3 * (4 * 1))))
...by extension ...
data Tree a = Leaf a | Branch (Tree a) (Tree a)
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree f g (Leaf x) = f x
foldTree f g (Branch x y) = g (foldTree f g x) (foldTree (f g y)
Then you recognize that the GoF calls this the Visitor pattern, because certain stupid languages don't have higher-order functions or algebraic data types, and so you need to make the equivalencies between concrete subclass => ADT constructor, Visitor => function, and object state => return value. Suddenly a lot of modularized compiler libraries (eg. LLVM) make a lot more sense.
Then you realize that a map is nothing but a list-fold where the binary operation is constrained to be the composition of some arbitrary function of the element together with a cons operator:
map :: (a -> b) -> [a] -> [b]
map f = foldr ((:) . f) []
The cool thing about this formalism is that it makes it explicit that f depends only upon the single element of the sequence, and that the ordering of the resulting list is independent of the actions of f. In other words, map can be parallelized. And that lays the groundwork for MapReduce, which lays the groundwork for massive-scale parallel data processing.
What lays the groundwork any massive-scale parallel data processing is a lot of good engineering, being aware of the common execution scenarios and relations to the environment (incl. HW). Plus tinkering with little devilish "details".
Pretty much the opposite of the (true but trivial) concept that ordering of the result is independent of the map function.
TL;DR What you wrote at the end sounded a bit analogous to saying startups succeed because of their idea, while they succeed for a number of things -- mostly the execution and how much other people like the idea in the real world.
Well, any real-world engineering problem is going to have a lot success factors, far more than can be enumerated in a post on an Internet message board.
The general point is that you aren't going to succeed unless you understand those building blocks in enough detail that you can take them apart and put them back together again in new ways. Map & reduce are concepts from functional programming, usually explained in Scheme or Haskell. MapReduce is a C++ framework. To go from one to another, you not only need to understand the nitty-gritty engineering details, but you also need to understand the fundamental computing concepts well enough to translate them into languages and use-cases that they weren't originally intended for.
(Side note: the MapReduce framework actually bears less resemblance to map & reduce than most people think. The "map" phase is a combination map & unfold, because you're not only iterating over the input, but you can output multiple times for a given input element. Think of running a word count over web pages: you have to parse the page and output multiple words per page. And the "reduce" phase is only a reduce within keys: it's really a map between keys, because the output is required to have the same keys as the input to the phase. I've often wished for a separate "re-key" phase, where the values output from the reduce phase could be reshuffled under a different key.)
I don't like the preachy tone but I like the way you disassembled your own argument in the side note there :-)
To avoid misunderstanding, I'm a fan of functional programming too. But the intersection of the MapReduce framework and map&reduce of Scheme and Haskell is mostly in the name and in some core math concepts that are ageless (predate programming and lambda calculus).
The real benefit comes from when you understand the concepts behind map and fold. If you realize that fold is nothing but replacing each n-ary constructor of an algebraic data type with an n-ary function, then you recognize that you can do the same thing for data structures besides sequences, like binary trees, graphs, and ASTs. There you're getting some benefit, because there's no built-in language syntax for iterating over those.
Then you recognize that the GoF calls this the Visitor pattern, because certain stupid languages don't have higher-order functions or algebraic data types, and so you need to make the equivalencies between concrete subclass => ADT constructor, Visitor => function, and object state => return value. Suddenly a lot of modularized compiler libraries (eg. LLVM) make a lot more sense.Then you realize that a map is nothing but a list-fold where the binary operation is constrained to be the composition of some arbitrary function of the element together with a cons operator:
The cool thing about this formalism is that it makes it explicit that f depends only upon the single element of the sequence, and that the ordering of the resulting list is independent of the actions of f. In other words, map can be parallelized. And that lays the groundwork for MapReduce, which lays the groundwork for massive-scale parallel data processing.