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

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

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

    躺在沙灘上的小豬

    快樂的每一天

    Martin Fowler:閉包

    Martin Fowler:閉包
    原著:Martin Fowler  http://martinfowler.com/bliki/Closures.html

    翻譯:huangpuzhuang.com>

    http://www.ruby-cn.org/

    另外一片文章總結了各種語言實現的本文中的例子。

    閉包(Closures)在各種語言中的例子

    2004/11/23

    本文地址:http://www.ruby-cn.org/articles/closures.html

        隨著人們對動態語言興趣的日益濃厚,越來越多的人都遇到了閉包(Closures )和或塊(Blocks)等概念。有著C/C++/Java/C#等語言背景的人因為這些語言本身沒有閉包這個概念,所以可能不太了解閉包。本文將簡單的介紹一下閉包的概念,那些有大量支持閉包語言編程經驗的人也許覺得本文不會太有意思。

        閉包的概念已經提出很長時間了。我第一次碰到這它是在smalltalk中,那時候還叫做塊(blocks)。Lisp語言中用的很多。Ruby中也有同樣的功能-這也是Ruby用戶喜歡Ruby的一個原因。

        本質上來說,一個閉包是一塊代碼,它們能作為參數傳遞給一個方法調用。我將通過一個簡單的例子來闡述這個觀點。假設我們有一個包含一些雇員對象的列表,然后我想列出職位為經理的員工,這樣的員工可以通過IsManager判斷。在C#里,我們可能會寫出下面類似的代碼:

      public static IList Managers(IList emps) {
        IList result = new ArrayList();
        foreach(Employee e in emps)
          if (e.IsManager) result.Add(e);
        return result;
      }
    

        在一種支持閉包的語言中,比如Ruby,我們可以這樣寫:

      def managers(emps)
    	return emps.select {|e| e.isManager}
      end
      

        select是Ruby中定義的集合結構中的一個方法,它接受一個block,也就是閉包,作為一個參數。在Ruby中,閉包寫在一對大括號中(不止這一種方法,另一種為do .. end)。如果這個塊也接受參數,你可以將這些參數放到兩個豎線之間。select方法循環迭代給定的數組,對每個元素執行給定的block,然后將每次執行block返回true的元素組成一個新的數組再返回。

        現在,如果你是C程序員你也許要想,通過函數指針也可以實現,如果你是JAVA程序員,你可能回想我可以用匿名內類來實現,而一個C#者則會想到代理(delegate)。這些機制和閉包類似,但是它們和閉包之間有兩個明顯得區別。

        第一個是形式上的不同(The first one is a formal difference)。閉包可以引用它定義時候可見的變量。看看下面的方法:

    def highPaid(emps)
    	threshold = 150
    	return emps.select {|e| e.salary > threshold}
    end
      

        注意select的block代碼中引用了在包含它的方法中的局部變量,而其它不支持真正閉包的語言使用其它方法達到類似功能的方法則不能這樣做。閉包還允許你做更有趣的事情,比如下面方法:

    def paidMore(amount)
    	return Proc.new {|e| e.salary > amount}
    end
    

        這個方法返回一個閉包,實際上它返回一個依賴于傳給它的參數的閉包。我可以用一個參數創建一個這樣的方法,然后再把它賦給另一個變量。

    highPaid = paidMore(150)
    

        變量 highPaid 包含了一段代碼(在Ruby中是一個Proc對象),這段代碼將判斷一個對象的salary屬性是否大于150。我們可以這樣使用這個方法:

    john = Employee.new
    john.salary = 200
    print highPaid.call(john)
      

          表達式highPaid.call(john)調用我之前定義的代碼,這時候此代碼中的amount已經在創建這方法的時候綁定為150。即使現在我執行print 的時候,150已經不在它的范圍內了,但是amount和150之間的綁定依然存在。

        所以,閉包的第一個關鍵點是閉包是一段代碼加上和定義它的環境之間的綁定(they are a block of code plus the bindings to the environment they came from)。這是閉包和函數指針等其它相似技術的不同點(java匿名內類可以訪問局部變量,但是只有當這些內類是final的時候才行)。

        第二個不同點不是定義形式的不同,但是也同樣重要。(The second difference is less of a defined formal difference, but is just as important, if not more so in practice)。支持閉包的語言允許你用很少的語法去定義一個閉包,盡管這點可能不是很重要的一點,但我相信這點是至關重要的-這是使得人們能很自然的使用閉包的關鍵點。看看Lisp,Smalltalk和Ruby,閉包遍布各處-比其它語言中類似的使用多很多。綁定局部變量是它的特點之一,但我想最大的原因是使用閉包的語法和符號非常簡單和清楚。

        一個很好的相關例子是從Smalltalk程序員到JAVA程序員,開始時很多人,包括我,試驗性的將在Smalltalk中使用閉包的地方在Java中使用匿名內類來實現。但結果使得代碼變得混亂難看,所以我們不得不放棄。

       我在Ruby經常使用閉包,但我不打算創建Proc對象,然后傳來傳去。大多數時間我用閉包來處理前面我提到的select等基于集合對象的方法。閉包另一個重要用途是'execute around method',比如處理一個文件:

    File.open(filename) {|f| doSomethingWithFile(f)}
    

       這里open方法打開一個文件,然后執行給定的block,然后關閉它。這樣處理非常方便,尤其是對事務(要求commit或者rollback),或者其它的你需要在處理結束時候作一些收尾處理的事情。我在我的xml文檔轉換中廣泛使用這個優點。

       閉包的這些用法顯然遠不如用Lisp語言的人遇到的多,即使我,在使用沒有閉包支持的語言的時候,也會想念這些東西。閉包就像一些你第一眼見到覺得不怎么樣的東西,但你很快就會喜歡上它們。

    其它語言例子

    Joe Walnes在blog中提供了 closures in the next version of C#。這個例子是靜態類型語言的,基于delegate,且需要delegate關鍵字。

    更新: Ivan Moore提供類類似的 Python 的例子

    更新: Vadim Nasardinov 讓我知道了來自Guy Steeleled的 closures in Java 這個有趣的珍聞。

     譯者注:如你想知道上面例子中文件對象是怎么自己關閉的,請看http://blog.csdn.net/ruby_cn/archive/2004/11/23/192588.aspx,希望可以找到答案。翻譯的不好,請多原諒。歡迎交流。括號之中的英語實在是不知如何很好翻譯,所以保留了下來。

    posted on 2005-09-20 13:37 martin xus 閱讀(298) 評論(0)  編輯  收藏 所屬分類: other

    主站蜘蛛池模板: 99re6在线视频精品免费下载| caoporm碰最新免费公开视频| 99视频在线免费| 久久久久久a亚洲欧洲AV| 巨胸狂喷奶水视频www网站免费| 免费人成视频在线观看不卡| 高h视频在线免费观看| 亚洲AV中文无码乱人伦| 精品一区二区三区免费毛片| 免费一级特黄特色大片在线| 一级毛片免费播放男男| 亚洲中文字幕无码久久精品1| 特级做A爰片毛片免费看无码| 国产亚洲一区二区三区在线| 日韩精品久久久久久免费| 亚洲人成电影福利在线播放 | 中国一级全黄的免费观看| 亚洲国产av一区二区三区| 国产精品免费久久久久电影网| 久久精品国产亚洲Aⅴ蜜臀色欲| 国产在线观a免费观看| 亚洲AV区无码字幕中文色| 4399影视免费观看高清直播| 久久一本岛在免费线观看2020| 亚洲国产精品成人精品无码区在线| 无码日韩精品一区二区免费暖暖| 亚洲日本在线观看网址| 成人免费视频试看120秒| 一区二区三区在线观看免费| 亚洲午夜精品一区二区| 97无码免费人妻超级碰碰碰碰| 暖暖免费中文在线日本| 亚洲av片劲爆在线观看| 免费无遮挡无码视频网站| 一级毛片大全免费播放下载 | 最近中文字幕免费mv在线视频| 亚洲中文字幕AV每天更新| 久久综合亚洲色HEZYO国产| 亚欧免费视频一区二区三区 | 久久A级毛片免费观看| 亚洲精品天堂无码中文字幕|