One day, you are browsing your code and find that there are two large pieces of code that are almost the same. In fact, they are exactly the same - except one is about Spaghetti and the other is about Chocolate Moose.
// A small example:
alert("I want to eat pasta!");
alert("I want to eat chocolate mousse!");
Hmm , this example happens to be written in JavaScript, but even if you don’t understand JavaScript, you should be able to understand what it is doing.
Copying code is not good. So, you create a function
function SwedishChef(food){
alert("I want to eat" food "!");
}
SwedishChef("pasta");
SwedishChef("Chocolate Mousse");
Ok, this is just a very small example, I believe you can imagine a more practical example. This code has many advantages, all of which you have heard tens of thousands of times: maintainability, readability, abstraction = good!
Now you notice that there are two other pieces of code that are almost identical to them, except that one repeatedly calls a function called BoomBoom, and the other repeatedly calls a function called PutInPot. Other than that, the two pieces of code are almost identical:
alert("Get the lobster");
PutInPot("lobster");
PutInPot("water");
alert("Get the chicken");
BoomBoom("Chicken");
BoomBoom("Coconut Sauce");
Now we need to find a way so that you can use one function as a function of another parameter. This is an important capability, because it is easier for you to write the framework code as a function (emu note: remember the template method pattern, right?).
function Cook( i1, i2, f ){
alert("get" i1);
f(i1);
f(i2);
}
Cook( "Lobster", "Water", PutInPot );
Cook( "Chicken", "Coconut Sauce", BoomBoom );
Look, we actually passed the function as a calling parameter!
Can your programming language do it?
Wait... If we already have the specific implementation code of functions such as PutInPot and BoomBoom (and do not need to reuse them elsewhere), then writing them into function calls using inline syntax is not Is it prettier than explicitly declaring these two functions?
Cook( "lobster",
"water",
function(x) { alert("pot " x); } );
Cook( "chicken",
"Coconut Sauce",
function(x) { alert("boom " x); } );
Yeah, so convenient! Please note that I just created a function out of the blue, I didn’t even think about naming it, I just took it by the ear and dropped it into a function.
When you think of anonymous functions as parameters, you probably think of code that performs the same operation on every element in an array.
var a = [1,2,3];
for (i=0; i
}
for (i=0; i
}
It is often necessary to do the same for all elements in the array thing, so you can write a function like this to help:
function map(fn, a){
for (i = 0; i a [i] = fn(a[i]);
}
}
Now you can change the above to:
map( function(x){return x*2 ;}, a );
map( alert, a );
Another common task is to sum up all the elements in an array in some general way:
function sum(a){
var s = 0;
for (i = 0; i s = a[i];
return s;
}
function join(a){
var s = "";
for (i = 0; i s = a[i];
return s;
}
alert(sum([1,2,3]));
alert(join(["a","b","c"]));
sum They look very similar to join. You may want to abstract them into a generic function that sums up all the elements in the array according to some algorithm:
function reduce(fn, a, init){
var s = init;
for (i = 0; i s = fn( s, a[i] );
return s;
}
function sum(a){
return reduce( function(a, b){ return a b; }, a, 0);
}
function join(a){
return reduce( function(a, b){ return a b; }, a, "" );
}
Many early programming languages were unable to do this. Some languages allow you to do it, but make it difficult (e.g. C has function pointers, but you have to declare and define the function elsewhere). Object-oriented languages also do not guarantee what you can do with functions (treat functions as objects?).
If you want to treat a function as a class of objects, Java requires you to create an object with a single method, called an operator object. Many object-oriented languages require you to create a complete file for each class, and development like this is really fast. If your programming language requires you to use operator objects to wrap methods (rather than treating methods themselves as objects), you are not getting the full benefits of a modern (dynamic) programming language. Why not give it a try and see if you can return it and get some money back?
What’s the benefit of not having to write functions that do nothing but do something with each element through an array?
Let’s look back at the map function. When you want to do something with each element in an array, you probably don't care which element is done first. Whether you start execution from the first element or the last element, your result will be the same, right? If you have 2 CPUs on hand, you can write code so that they each work on half of the elements, so map is twice as fast.
Or, use your imagination. Imagine that you have tens of millions of servers distributed in several data centers around the world. You have a really big array. Well, let’s use it a little more. Use your imagination and imagine that this array records the contents of the entire Internet. Also, now you can execute map on thousands of servers simultaneously, allowing each server to solve a small part of the same problem.
So in this example, writing a very fast code to search the entire Internet is as simple as calling the map function with a simple string searcher (operator) as a parameter.
I hope you noticed a really interesting point. If you want to turn the map/reduce pattern into a technology that is useful to everyone and can be used by everyone immediately, you It only takes a super genius to write the most important part of the code so that map/reduce can run on a huge array of parallel computers, and then the rest of the old code that has always worked well in a single loop can still remain correct Running, the only difference is that it is n times faster than the original single-machine running. This means that they all suddenly turn into code that can be used to solve a huge problem.
Let me say it again. By abstracting the concept of "loop", you can implement the "loop" process in any way you like, including making the loop iteration speed scale with the hardware computing power. Maintain satisfactory synchronized growth.
You should now be able to understand why the recent dissatisfaction with those computer science students who have not been taught anything but Java: ( http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html ):
Without understanding functional programming, you can't invent MapReduce, the algorithm that makes Google so massively scalable. The terms Map and Reduce come from Lisp and functional programming. MapReduce is, in retrospect, obvious to anyone who remembers from their 6.001-equivalent programming class that purely functional programs have no side effects and are thus trivially parallelizable. The very fact that Google invented MapReduce, and Microsoft didn't, says something about why Microsoft is still playing catch up trying to get basic search features to work, while Google has moved on to the next problem: building Skynet^H^H^H^H^H^H the world's largest massively parallel supercomputer. I don't think Microsoft completely understands just how far behind them are on that wave.
If you don’t understand functional programming, you can’t invent MapReduce, the algorithm that makes Google’s computing power so scalable. The terms Map and Reduce are derived from Lisp language and functional programming... (This is the content of another article, emu does not fully understand the ins and outs of the various terms in it, so I will not translate it)
I hope you understand now that (dynamic) programming languages that treat functions as basic types allow you to better abstract during the programming process, which means making the code leaner, more functional, more reusable, and more efficient. Extensible. Many Google applications use the Map/Reduce model, so they can all benefit from it when someone optimizes it or fixes defects.
I’m going to be a little more verbose. I think the most productive programming language is one that allows you to abstract at different levels. The old FORTRAN language used to not let you write functions. C has function pointers, but they are very ugly, ugly, ugly, ugly, do not allow anonymous declarations, and cannot be implemented when using them and must be implemented elsewhere. Java lets you use operator objects, something even uglier. As Steve Yegge said, Java is a kingdom of nouns (http://steveyegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html).
Author's Note: FORTRAN is mentioned here, but the last time I used FORTRAN was 27 years ago. FORTRAN has functions, and what I was thinking about when I was coding was probably the GW-BASIC language. (emu note, basic does only have so-called subroutines and go-sub statements, which only reorganize the code structure. There are no parameters and call stacks, so there are no real function calls)
Translator's Note: Original author The title "Can your programming language do this?" is actually not the real value of this article. I repost this article not because the original author can master the basic skills of the language, but because this is A demonstration of the map/reduce model.