`
RednaxelaFX
  • 浏览: 3022727 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

关于对象与闭包的关系的一个有趣小故事

阅读更多
在一个邮件列表里看到一段很有趣的小故事:
RE: What's so cool about Scheme?
Anton van Straaten 写道
  The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said "Master, I have heard that objects are a very good thing - is this true?"  Qc Na looked pityingly at his student and replied, "Foolish pupil - objects are merely a poor man's closures."

  Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire "Lambda: The Ultimate..." series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system.  He learned much, and looked forward to informing his master of his progress.

  On his next walk with Qc Na, Anton attempted to impress his master by saying "Master, I have diligently studied the matter, and now understand that objects are truly a poor man's closures." Qc Na responded by hitting Anton with his stick, saying "When will you learn? Closures are a poor man's object." At that moment, Anton became enlightened.

哈哈,Anton用十分风趣的口吻把对象与闭包之争的“宗教性”描写了出来。无论从哪个角度出发都能说得通,所以实在没什么争执的必要……
分享到:
评论
2 楼 RednaxelaFX 2008-09-21  
我不理解你不理解的是什么……闭包的定义很好理解撒。要点有俩:
1、一个含有自由变量的函数;
2、这些自由变量所在的环境。
外部环境持有内部函数所使用的自由变量,对内部函数形成“闭包”,就这样。
简单但不严格的说,一个函数的“自由变量”就是既不是参数也不是局部变量的变量。

一个纯粹(无副作用)的函数如果不含有自由变量,那么每次用相同的参数调用后的得到的结果肯定是一样的。但如果一个函数含有自由变量,那么调用返回的结果不但依赖于参数的值,还依赖于自由变量的值。因此一个含有自由变量的函数要正确执行,必须保证其所依赖的外围环境的存在。

基于类的面向对象程序语言中有一种情况,就是方法是用的自由变量是来自其所在的类的实例的。像这样:
class Foo {
    private int x;
    int AddWith( int y ) { return x + y; }
}

这样的AddWith()有一个参数y和一个自由变量x,其返回的值既依赖于参数的值也依赖于自由变量的值。为了让AddWith()正确工作,它必须依附于Foo的一个实例,不然就得不到x的值了(称为:“变量i未与值相绑定”)。很好理解对吧。不过面向对象的语言里一般不把类称为闭包,没为什么,就是种习惯。
当然严格来说方法所捕获的自由变量不是i,而是this;x是通过this来访问到的,完整写出应该是this.x。

如果这个“外围环境”来自一个外围函数,并且内部函数可以作为返回值返回,那么外围函数的局部环境就不能在调用结束时就撤销。也就是说不能在栈上分配空间。
function AddWith(x) {
    return function(y) {
        return x + y
    }
}

这样的内部函数有一个参数y和一个自由变量x。x在外围函数AddWith()里是一个参数,也就是一个“已绑定了值的变量”(bound variable)。AddWith()的局部作用域中含有内部函数所使用的自由变量,对内部函数形成闭包。为了让返回出去的内部函数能正常工作,这个内部函数必须依附于一个能提供x的值的环境,也就是AddWith()提供的闭包。这样我们就能够:
var addFive = AddWith(5)
var seven = addFive(2) // 2+5=7


全局变量是一种特殊的自由变量。
1 楼 lwwin 2008-09-21  
closure的定义每次都被FX搞糊涂=v=+

不知道FX大自己的理解是怎样的呢~很微妙似的……

相关推荐

    关系闭包的计算

    实验目的:熟悉warshall算法,...实验内容:从键盘输入一个关系的关系矩阵,自动求出自反闭包、对称闭包和传递闭包。 计算传递闭包用Warshall算法。 #include<iostream> using namespace std; #define N 4 class jz

    离散数学-关系,集合,求自反闭包,对称闭包,传递闭包

    离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包,传递闭包 离散数学-关系,集合,求自反闭包,对称闭包...

    二元关系的闭包运算

    离散数学中关于二元关系闭包运算的判断便程,可视化,可在visual studio先运行

    离散实验报告求有限集上给定关系的自反、对称和传递闭包

    自反闭包是指关系矩阵中的主对角线全部置为1,即每个元素在关系中都与自己相关。这种闭包可以用于判断关系是否满足自反性质。例如,在社交网络中,如果两个用户之间存在关注关系,那么在关系矩阵中,他们之间的元素...

    求闭包和最小依赖集

    在关系数据库中,闭包是指一个或多个属性的集合,它们之间存在函数依赖关系。给定一个属性集U={A,B,C,...},我们可以定义其闭包为U+,它是U的所有可能的函数依赖关系的集合。 例如,给定一个属性集U={A,B},如果...

    关系性质判断及闭包的求法

    对离散数学中二元关系的判定及自反、对称、传递闭包的计算

    江西财经大学关系的传递闭包

    关系的传递闭包 c++语言描述 绝对可以实现的 下载吧

    极小S-负传递闭包的一个求解方法

    主要研究了负传递的性质,利用余蕴涵的概念,给出了有限论域上模糊关系的极小S-负传递闭包的一个求解方法,进一步丰富了模糊关系传递性的对偶性质——负传递性的研究。

    Java闭包 Java闭包

    在2013年发布的 JavaSE8 中包含一个叫做 Lambda Project 的计划,在 JSR-335 草案 中有描述。 JSR-335 将闭包引入了 Java 。闭包在现在的很多流行的语言中都存在,例如 C++、C# 。闭包允许我 们创建函数指针,并把...

    数据库求属性集闭包&函数依赖闭包

    声明:以下仅个人观点,若有错误,敬请指正O(∩_∩)O~ 关键点 1) 将函数依赖用multimap,string> 存储,因为函数依赖可能...对每一个子集求其闭包,记为Ri+;然后求Ri+的所有子集记为(Ri+)j;最后做映射Rià(Ri+)j。

    基于闭包的关系模式全部主属性的多项式时间算法

    基于闭包的关系模式全部主属性的多项式时间算法

    JavaScript核心(对象、原型、继承、上下文、闭包、this).pdf

    面向对象概念(对象封装,各种继承,闭包原理,this作用域等)介绍清晰易懂

    C++对称闭包对称闭包

    用矩阵求对称闭包。简洁,轻松学习,相互交流。

    计算NFA中ε闭包

    计算NFA中各个状态的闭包,从键盘上输入一个NFA的描述信息(输入格式自行定义),将 该NFA的描述信息保存到合适的数据结构中,然后计算出NFA中每个状态的ε_closure。

    c++求传递闭包

    传递闭包C++描述,应用c++语言描述传递闭包算法

    数据库属性闭包与应用

    本文结合自己在教学过程中的体会谈谈属性闭包在关系数据理论中的应用。

    内存泄露,闭包 内存泄露,闭包 内存泄露,闭包

    内存泄露,闭包 内存泄露,闭包 内存泄露,闭包

    传递闭包实现

    即在数学中,在集合 X 上的二元关系 R 的传递闭包是包含 R 的 X 上的最小的传递...再比如,如果 X 是空港的集合而关系 xRy 为“从空港 x 到空港 y 有直航”,则 R 的传递闭包是“可能经一次或多次航行从 x 飞到 y”。

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下...

Global site tag (gtag.js) - Google Analytics