闭包使用的一个陷阱

简介:
来源: 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( 1 4 )]
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都采用列表推断。

文章转自庄周梦蝶  ,原文发布时间 2010-07-09
目录
相关文章
|
6月前
|
自然语言处理 编译器 C语言
C语言编程陷阱:词法陷阱
推荐一个零声学院免费教程,个人觉得老师讲得不错, 服务器课程
22 0
|
8月前
什么是闭包,闭包的特性
什么是闭包,闭包的特性
|
3天前
什么是闭包?手写一个闭包函数
什么是闭包?手写一个闭包函数
8 0
|
5月前
|
人工智能 自然语言处理 前端开发
闭包是什么?闭包的用途是什么?
闭包是什么?闭包的用途是什么?
|
10月前
|
安全 Python
Python闭包与闭包陷阱
在 Python 中,闭包是一种特殊的函数,它能够记住它所在的环境(也称作上下文)。这意味着闭包能够访问定义它的作用域中的变量。闭包通常用于封装数据和提供对外部访问的接口。
|
前端开发 JavaScript
都2020年了,你还不懂什么是闭包吗---深入理解闭包这一篇文章足以
都2020年了,你还不懂什么是闭包吗---深入理解闭包这一篇文章足以
57 0
|
Web App开发 JavaScript 前端开发
应该如何理解闭包
应该如何理解闭包
应该如何理解闭包
什么是闭包?闭包的用途是什么?闭包的缺点是什么?
变量的作用域有两种:全局变量和局部变量; 函数内部可以直接读取全局变量; 在函数外部无法读取函数内的局部变量。 能够读取其他函数内部变量的函数,就是闭包
88 0
|
自然语言处理 JavaScript 前端开发
【闭包概念】关于闭包概念不同解读——你可以自己理解。
写在前面: 闭包是被讲烂的内容,但是当我不了解的情况下,看过很多教程,听过很多道理,还是无法完全理解闭包这个东西。所以想要写一篇比较详细,前端小白也能够真正理解闭包概念的干货文章,本文参考很多闭包资料,希望能真正把闭包这个东西讲清楚,喜欢的朋友可以点个赞,或者点波关注。 首先需要了解一波js变量的作用域以及变量的生存周期。 前几天我发在掘金上面了,下面是一个内容概要,墙裂推荐所有小伙伴,还是点进去学习一波,作用域这个问题可以说是闭包最为重要的内容。 里面的内容包括: 1.变量的作用域(变量的有效范围)。2.变量作用域,js高级程序设计(红宝书)中的解释。3.红宝书中的作用域链栗子(还有一个例子
129 0
【闭包概念】关于闭包概念不同解读——你可以自己理解。
【Swift4】(6) 闭包 | 闭包应用 | 闭包作为函数参数 | 捕获特性
【Swift4】(6) 闭包 | 闭包应用 | 闭包作为函数参数 | 捕获特性