<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    心有多大舞臺便有多大

    Embrace changes, pursue excellence, share niceness.

    你的編程語言可以這樣做嗎?(map/reduce的js示范) (轉)

    有一天,你在瀏覽自己的代碼,發(fā)現(xiàn)有兩大段代碼幾乎一樣。實際上,它們確實是一樣的——除了一個關于意大利面(Spaghetti)而另一個關于巧克力慕思(Chocolate Moose)。
     // 一個小例子:
     
     alert("偶要吃意大利面!");
     alert("偶要吃巧克力慕思!");
    嗯,這個例子碰巧是用javascript寫的,不過你就算不懂JavaScript,應該也能明白它在干什么。

    拷貝代碼不好。于是,你創(chuàng)建了個函數(shù)
     function SwedishChef( food ){
     alert("偶要吃" + food + "!");
     }
     SwedishChef("意大利面");
     SwedishChef("巧克力慕思");
    Ok,這只是一個很小很小的例子而已,相信你能想像到個更實際一點的例子。這段代碼有很多優(yōu)點,你全都聽過幾萬次了:可維護性、可讀性、抽象性 = 好!

    現(xiàn)在你留意到有另外兩段代碼幾乎跟它們一模一樣,除了一個反復調用一個叫BoomBoom的函數(shù),另一個反復調用一個叫PutInPot的。除此之外,這兩段代碼簡直沒什么兩樣:
     alert("拿龍蝦");
     PutInPot("龍蝦");
     PutInPot("水");
     alert("拿雞肉");
     BoomBoom("雞肉");
     BoomBoom("椰子醬");
    現(xiàn)在要想個辦法,使得你可以將一個函數(shù)用作另一個函數(shù)的參數(shù)。這是個重要的能力,因為你更容易將框架代碼寫成一個函數(shù)(emu注:還記得template method模式吧?)。
     function Cook( i1, i2, f ){
     alert("拿" + i1);
     f(i1);
     f(i2);
     }
     Cook( "龍蝦", "水", PutInPot );
     Cook( "雞肉", "椰子醬", BoomBoom );
    看看,我們居然把函數(shù)當成調用參數(shù)傳遞了!

    你的編程語言能辦到嗎?

    等等……假如我們已經(jīng)有了PutInPot和BoomBoom這些函數(shù)的具體實現(xiàn)代碼(而且又不需要在別的地方重用它們),那么用內聯(lián)語法把它們寫進函數(shù)調用里面不是比顯式的聲明這兩個函數(shù)更漂亮嗎?
     Cook( "龍蝦",
     "水",
     function(x) { alert("pot " + x); } );
     Cook( "雞肉",
     "椰子醬",
     function(x) { alert("boom " + x); } );
    耶,真方便!請注意我只是隨手創(chuàng)建了個函數(shù),甚至不用考慮怎么為它起名,只要拎著它的耳朵把它往一個函數(shù)里頭一丟就可以了。

    當你一想到作為參數(shù)的匿名函數(shù),你也許想到對那些對數(shù)組里的每個元素進行相同操作的代碼。
     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]);
     }
    常常要對數(shù)組里的所有元素做同一件事,因此你可以寫個這樣的函數(shù)來幫忙:
     function map(fn, a){
     for (i = 0; i < a.length; i++){
     a[i] = fn(a[i]);
     }
     }
    現(xiàn)在你可以把上面的東西改成:
     map( function(x){return x*2;}, a );
     map( alert, a );
    另一個常見的任務是將數(shù)組內的所有元素按照某總方式匯總起來:
     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長得很像,你也許想把它們抽象為一個將數(shù)組內的所有元素按某種算法匯總起來的泛型函數(shù):
     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, "" );
     }
    許多早期的編程語言沒法子做這種事。有些語言容許你做,卻又困難重重(例如C有函數(shù)指針,但你要在別處聲明和定義函數(shù))。面向對象語言也不確保你用函數(shù)可以干些啥(把函數(shù)當對象處理?)。

    如 果你想將函數(shù)視為一類對象,Java要求你建立一個有單方法的對象,稱為算子對象。許多面向對象語言要你為每個類都建立一個完整文件,像這樣開發(fā)可真叫 快。如果你的編程語言要你使用算子對象來包裝方法(而不是把方法本身當成對象),你就不能徹底得到現(xiàn)代(動態(tài))編程語言的好處。不妨試試看你可否退貨拿回 些錢?

    不用再寫那些除了經(jīng)過一個數(shù)組對每個元素做一些事情之外一無是處的函數(shù),有什么好處?

    讓我們看回map函數(shù)。當你要對數(shù)組內的每個元素做一些事,你很可能不在乎哪個元素先做。無論由第一個元素開始執(zhí)行,還是是由最后一個元素執(zhí)行,你的結果都是一樣的,對不?如果你手頭上有2個CPU,你可以寫段代碼,使得它們各對一半的元素工作,于是乎map快了兩倍。

    或 者,發(fā)揮一下想像力,設想你在全球有千千萬萬臺服務器分布在全世界的若干個數(shù)據(jù)中心,你有一個真的很大很大的數(shù)組,嗯,再發(fā)揮一下想像力,設想這個數(shù)組記 錄有整個互聯(lián)網(wǎng)的內容。還了,現(xiàn)在你可以在幾千臺服務器上同時執(zhí)行map,讓每臺服務器都來解決同一個問題的一小部分。

    那么在這個例子里面,編寫一段非??斓拇a來搜索整個互聯(lián)網(wǎng)這個問題,其實就和用一個簡單的字符串搜索器(算子)作為參數(shù)來調用map函數(shù)一樣簡單了。

    希 望你注意到一個真正有意思的要點,如果你想要把map/reduce模式變成一個對所有人都有用,對所有人都能立刻派上用場的技術,你只需要一個超級天才 來寫最重要的一部分代碼,來讓map/reduce可以在一個巨大的并行計算機陣列上運行,然后其他舊的但是一向在單一個循環(huán)中運行良好的代碼,仍可以保 持正確的運行,惟一的差別只是比原來單機運行快了n倍。這意味著它們都一不留神突然變成可以被用來解決一個巨大的問題的代碼。

    讓我再啰嗦一下,通過把“循環(huán)”這個概念加以抽象,你可以把用任何你喜歡的方式來實現(xiàn)“循環(huán)”過程,包括可以實現(xiàn)讓循環(huán)迭代速度隨著硬件計算能力保持令人滿意的同步增長。

    你現(xiàn)在應該可以明白不久為何對那些對除了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 they are on that wave.

    不理解函數(shù)式編程,你就發(fā)明不了MapReduce這個讓Google的計算能力如此具有可擴展性的算法。Map和Reduce這兩個術語源自Lisp語言和函數(shù)式編程……(這是另一篇文章的內容,emu也不是很理解其中的各種說法的來龍去脈,就不翻譯了)

    我希望你現(xiàn)在明白,把函數(shù)當成基本類型的(動態(tài))編程語言能讓你在編程過程中更好的進行抽象化,也就是使代碼精悍、功能更內聚、更具可重用性及更具有擴展性。很多的Google應用使用Map/Reduce模式,因此一有人對其優(yōu)化或修正缺陷,它們就都可以從中得益。

    我 準備要再羅嗦一下,我認為最有生產(chǎn)力的編程語言莫過于能讓你在不同層次上都可以進行抽象化的。老掉牙的FORTRAN 語言以前是不讓你寫函數(shù)的注。C 有函數(shù)指針,可是它們都非常丑丑丑丑丑丑丑丑陋,不允許匿名聲明,又不能在用它們時實現(xiàn)它們而偏偏要放在別處去實現(xiàn)。Java讓你使用算子對象,一種更丑 陋的東西。正如Steve Yegge所述,Java是個名詞王國
    ( http://steveyegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html )。

    作者注:這 里提起了FORTRAN,不過我上次使用FORTRAN是27年前的事了。FORTRAN是有函數(shù)的,我碼字那會兒腦子里面想的大概是GW-BASIC語 言。(emu注,basic確實只有所謂的子程序和go-sub語句,作用只是重新組織代碼結構而已,沒有參數(shù)和調用堆棧,因此沒有真正的函數(shù)調用)

    譯者注:原作者起了《你的編程語言可以這樣做嗎》這個標題其實并不是這篇文章的真正價值所在,我轉這篇文章也不是因為原作者可以把語言的初級技巧玩得轉,而是因為這是一篇map/reduce模型的示范。

    posted on 2008-06-09 18:39 pony 閱讀(503) 評論(1)  編輯  收藏 所屬分類: 網(wǎng)站

    評論

    # re: 你的編程語言可以這樣做嗎?(map/reduce的js示范) (轉) 2008-06-19 14:12 pony

    今天看到apache上竟然有個項目Hadoop,是個java的map/reduce的實現(xiàn).  回復  更多評論   

    主站蜘蛛池模板: 亚洲日本VA中文字幕久久道具| 特黄aa级毛片免费视频播放| 精品国产日韩久久亚洲| 国产天堂亚洲国产碰碰| 日本视频在线观看永久免费| 国产精品视频免费一区二区| 亚洲国产精品无码一线岛国| 亚洲精品无码久久| 成人毛片视频免费网站观看| 亚洲av无码av制服另类专区| 亚洲国产AV一区二区三区四区| 日本免费中文字幕| 亚洲视频手机在线| xvideos永久免费入口| 久久久久久精品成人免费图片| 免费a级毛片无码a∨性按摩| 亚洲毛片在线免费观看| 两个人看的www高清免费观看| 日本免费电影一区| 亚洲国产成人精品无码一区二区 | 午夜福利不卡片在线播放免费| 国产AV无码专区亚洲AWWW| 亚洲av成人一区二区三区观看在线 | 免费少妇a级毛片| yellow视频免费在线观看| 亚洲大成色www永久网站| h片在线免费观看| 久久久久久亚洲精品无码| 日批视频网址免费观看| 亚洲无线电影官网| 免费萌白酱国产一区二区三区 | 国产男女猛烈无遮挡免费视频网站 | 亚洲国产精品无码久久一区二区| 韩日电影在线播放免费版| 亚洲国产精品自在线一区二区| 日韩免费一区二区三区在线| 青草久久精品亚洲综合专区| 中文字幕一精品亚洲无线一区| 又粗又大又黑又长的免费视频| 免费无遮挡无遮羞在线看 | 中文字幕无线码免费人妻|