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

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

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

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    閉包使用的一個陷阱

    Posted on 2010-07-09 23:52 dennis 閱讀(1729) 評論(4)  編輯  收藏 所屬分類: 動態語言

    來源:http://moonbase.rydia.net/mental/blog/programming/the-biggest-mistake-everyone-makes-with-closures.html

    看下面的Ruby代碼
    = []
    for x in 1..3
      k.push(
    lambda { x })
    end

    執行
    k[0].call

    你可能預期返回1,實際的結果卻是3。這是為何?這是因為在迭代過程中共用了同一個context,導致k中的三個閉包都引用了同一個變量x。不僅僅Ruby有這個問題,python也一樣
    = [lambda: x for x in xrange(14)]
    k[0]()

    Javascript同樣如此

    var k = [];
    for (var x = 1; x < 4; x++) {
      k.push(function () { 
    return x; });
    }
    alert(k[0]())


    解決這個問題很簡單,就是將閉包包裝到一個函數里,建立新的context,那么迭代過程中生成的閉包所處的context不同:
    def make_value_func(value)
      
    lambda { value }
    end
    = (1..3).map { |x| make_value_func(x) }

    這個時候,k[0].call正確地返回1。

    這個問題并非在所有支持閉包的語言里都存在,例如scheme中就沒有問題

    (define k '())
    (do ((x 1 (+ x 1)))
        ((
    = x 4'())
      (set! k (cons (lambda () x) k)))
    (set! k (reverse k))

    ((car k)) 
    =>1


    Erlang也沒有問題
    K=[ fun()->X end || X <- [1,2,3]].

    lists:map(fun(F)
    -> F() end,K).

    再試試Clojure:
    (def k (for [i (range 1 4)] (fn [] i)))
    (map #(
    %) k)

    同樣沒有問題。這里Erlang和Clojure都采用列表推斷。





    評論

    # re: 閉包使用的一個陷阱  回復  更多評論   

    2010-07-10 00:40 by Rain Yang
    Ruby 1.9.x 不會再這樣了。

    # re: 閉包使用的一個陷阱[未登錄]  回復  更多評論   

    2010-07-15 14:46 by sin
    actionscript同樣問題

    # re: 閉包使用的一個陷阱  回復  更多評論   

    2012-12-22 15:57 by Zhiqiang.Zhan
    這不是閉包的缺陷,這是因為Ruby,Python還有JavaScript這些支持函數式等編程語言中的block都不能形成閉包作用域,而你拿來對比的Erlang和Clojure的例子很不恰當,它的等價形式相當于Ruby中的
    k = []
    (1..3).each do |x|
    k.push(lambda {x})
    end

    puts k[0].call

    而這個剛好是OK的。
    這是因為do...end block形成了閉包,但是for ...end中的語句沒有形成新的閉包。

    # re: 閉包使用的一個陷阱  回復  更多評論   

    2013-11-04 02:45 by 我傻逼我自豪
    js例:
    var a = [];
    for (var x = 4; x >= 0; x--) {
    a.push(function (x) {
    return x;
    });
    }
    alert(a[4]());
    主站蜘蛛池模板: 污污视频网站免费观看| 免费人成视网站在线观看不卡| 国产乱色精品成人免费视频| 亚洲丝袜美腿视频| 高清永久免费观看| 免费a级毛片在线观看| 亚洲一卡2卡三卡4卡无卡下载| 毛片基地免费视频a| 久久精品免费全国观看国产| 67pao强力打造67194在线午夜亚洲 | 大陆一级毛片免费视频观看| 亚洲熟女综合色一区二区三区| 欧美男同gv免费网站观看 | 又硬又粗又长又爽免费看| 亚洲伊人久久成综合人影院| 大地资源在线资源免费观看| 精品亚洲A∨无码一区二区三区| 国产2021精品视频免费播放| 亚洲一久久久久久久久| 亚洲伊人久久综合中文成人网| 你是我的城池营垒免费看| 亚洲国产精品久久| 成人免费视频软件网站| 黄网站色成年片大免费高清| 亚洲深深色噜噜狠狠爱网站| 18未年禁止免费观看| 亚洲人成人伊人成综合网无码| 亚洲精品视频在线看| a级毛片黄免费a级毛片| 亚洲av无码国产综合专区 | 91麻豆国产免费观看| 亚洲欧美日韩中文字幕一区二区三区| 免费一级毛片在级播放| 免费视频精品一区二区三区| 一本天堂ⅴ无码亚洲道久久| 国产性爱在线观看亚洲黄色一级片| 无码日韩精品一区二区三区免费 | 羞羞的视频在线免费观看| 久久精品国产亚洲av麻豆| 久久WWW色情成人免费观看| 久草免费福利在线|