Search

12/09/2009

你的程式語言可以這樣做嗎? - The Joel on Software Translation Project

你的程式語言可以這樣做嗎? - The Joel on Software Translation Project

當你一想到作為參數的無名函數,你也許想到對某個陣列的元素進行相同動作的程式碼。

var a = [1,2,3];

for (i=0; i<a.length; i++) {
a[i] = a[i] * 2;
}

for (i=0; i<a.length; i++) {
alert(a[i]);
}

常常要對陣列內的所有元素做同一件事,因此你可以寫個這樣的函數來幫忙:

function map(fn, a) {
for (i = 0; i < a.length; i++) {
a[i] = fn(a[i]);
}
}

現在你可以將上面的東西寫成:

map( function(x){return x*2;}, a );
map( alert, a );

另一個常見的工作是將陣列內的所有元素按某種方法合起來:

function sum(a)
{
var s = 0;
for (i = 0; i < a.length; i++)
s += a[i];
return s;
}

function join(a)
{
var s = "";
for (i = 0; i < a.length; i++)
s += a[i];
return s;
}

alert(sum([1,2,3]));
alert(join(["a","b","c"]));

'sum'和'join'長得很像,你也許想將它們抽象化,變成將陣列內所有元素按某種方法合起來的泛型函數:

function reduce(fn, a, init)
{
var s = init;
for (i = 0; i < a.length; 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, "" );
}

讓我們回到'map'函數。對陣列內的每個元素做事時,很可能並不在乎哪個元素先做。無論由第一個還是最後一個元素開始,結果都是一樣的,對不對?如果你手頭上有2個CPU,就可以寫段程式碼,使得它們各對一半的元素工作,於是'map'就變快兩倍了。

或者你在全球有千千百百台伺服器(只是假設),還有一個很大很大的陣列,存放整個互聯網的內容(同樣也只是假設)。現在你可以在這些伺服器上執行'map',讓各台伺服器只處理問題很小的一部份。

tag: map reduce mapreduce

沒有留言: