<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]());
    主站蜘蛛池模板: 伊人久久综在合线亚洲91| 最近中文字幕大全免费视频 | 国产日韩一区二区三免费高清| 全部免费国产潢色一级| 亚洲精品无码久久久久YW| 天天看免费高清影视| 亚洲欧美日韩中文高清www777| 最近2019中文字幕免费看最新| 亚洲伊人精品综合在合线| 国产片AV片永久免费观看| 亚洲综合丁香婷婷六月香| 久久综合AV免费观看| 亚洲AV成人精品一区二区三区 | 亚洲黄片手机免费观看| 一边摸一边桶一边脱免费视频| 亚洲国模精品一区| 大地资源网高清在线观看免费| 亚洲AV成人精品网站在线播放| 久久久久久影院久久久久免费精品国产小说 | 精品日韩亚洲AV无码一区二区三区 | 亚洲第一街区偷拍街拍| 免费一级毛片正在播放| selaoban在线视频免费精品| 亚洲人成77777在线播放网站| 午夜不卡久久精品无码免费| 亚洲国产成人va在线观看网址| 毛片a级三毛片免费播放| 偷自拍亚洲视频在线观看99| 久久久久亚洲AV无码专区桃色| 成人性生交大片免费看中文| 亚洲最新中文字幕| 四虎永久在线精品视频免费观看| 一级做a毛片免费视频| 亚洲AV美女一区二区三区| 国产香蕉九九久久精品免费| 色婷婷综合缴情综免费观看| 日木av无码专区亚洲av毛片| 日日操夜夜操免费视频| 久久国产乱子精品免费女 | 亚洲精品无码久久久久久久| 蜜桃精品免费久久久久影院|