2008年3月20日星期四

JavaScript上的闭包(closure): 第二种说法

而Martin Fowler对闭包的介绍却是另外一种解释: 闭包就是一段可作为参数传递的代码。从他提供的示例来看只是个匿名函数,跟嵌套函数没有什么关系,其他人也给出了C#PythonJavaScript上的例子,却跟上面的不一样。
  1. Array.prototype.select = function(func)
  2. {
  3. var ary = [];
  4. for (var i = 0; i < this.length; ++i)
  5. {
  6. if (func(this[i]))
  7. ary[ary.length] = this[i];
  8. }
  9. return ary;
  10. };
  11. function managers_noclosure(emps) {
  12. var result = [];
  13. for (var i = 0; i < class="delimiters1">)
  14. {
  15. var e = emps[i];
  16. if (e.isManager) result[result.length] = e;
  17. }
  18. return result;
  19. }
  20. function managers(emps)
  21. {
  22. return emps.select(function (e){ return e.isManager; });
  23. }

而现在嚷嚷得比较厉害的Java支持也是依照这种概念: http://www.infoq.com/cn/news/2007/09/catching-up-with-closures

按照这种定义,闭包非常类似于C语言中的函数指针、C++里面的模板函数、Java中的内嵌类,虽然Martin Fowler在他文章里也在说明闭包跟这些概念的不同时提到了运行环境的问题,但似乎没有什么说服力,至少从例子上是看不出来的。

个人感觉,前面一种说法是正确的,这种说法不大对。虽然Martin Fowler的名气很大。

JavaScript上的闭包(closure)

闭包这个概念随着并发、函数式编程的复兴,也热乎了起来。”跟上Java闭包(Closure)的步伐“一文中说:
Mark Jason Dominus在Perl概述中的话语作为开场:在未来的三十年中,人们将会取笑那些发明没有闭包特性的语言的人,如同他们现在正取笑那些发明没有递归这种特性的语言的人是一个道理。
  • 定义
那么这是个啥东西? Wikipedia上对closure的解释是:
In computer science, a closure is a function that is evaluated in an environment containing one or more bound variables. When called, the function can access these variables. The explicit use of closures is associated with functional programming and with languages such as ML and Lisp. Constructs such as objects in other languages can also be modeled with closures.

In some languages, a closure may occur when a function is defined within another function, and the inner function refers to local variables of the outer function. At runtime, when the outer function executes, a closure is formed, consisting of the inner function’s code and references to any variables of the outer function required by the closure.
这个说法比较抽象。还是来看看实际的例子吧。
  • 实例说明
JavaScript中,简单的说法是: In JavaScript, if you use the function keyword inside another function, you are creating a closure.(摘自Morris Johns的JavaScript Closures for Dummies, 中文翻译可看这里: 在JavaScript中,什么是闭包)。
  1. function sayHello(name) {
  2. var text = 'Hello ' + name; // local variable
  3. var sayAlert = function() { alert(text); }
  4. return sayAlert;
  5. }
  6. var say = sayHello('Bob');
  7. say();

注 意sayAlert是sayHello的一个嵌套函数,当var say = sayHello('Bob')这行执行完之后,因为say是对内部函数sayAlert的一个引用,所以这个函数对象不会被释放,而sayAlert的 执行环境(execution context)也不会被释放,一个函数与它的数据、执行环境绑在一起,这个sayHello就是一个闭包了。

这里有好几个概念: 嵌套函数,函数引用,作用域链(scope chain),执行环境。从目前看见的资料来看,闭包的构成必须有这几个要素。
  • 作用
这个东西有什么作用呢,先看如下一个例子:
  1. var f, g;
  2. function foo() {
  3. var x = 0;
  4. f = function() { return ++x; };
  5. g = function() { return --x; };
  6. x = 1;
  7. print(f()); // "2"
  8. }
  9. foo();
  10. print(g()); // "1"
  11. print(f()); // "2"
  • 两个不同功能、相互独立的函数只能通过全局变量交换数据么(这里说语言本身提供的能力,而不是平台提供的能力)? 上面例子中两个函数都操作了变量x,但x并不是全局变量,但对于其他函数也是不可见的。可见第一个作用是提供另一种手段来供两段程序交换数据,同时保护变 量安全
  • 两个闭包建立之后,只需要根据两个引用就可以调用了,这两个引用相互独立,但又是完全自包含的,——这显然是函数式编程的风格了

2008年3月18日星期二

PyCon 2008总结

PyCon 2008前两天开了, 但国内的Python社区似乎都没有见到什么人关注(至少在CPUG的Planet of Woodpecker.org上没人提到这个, Google了一下也没有多少中文信息, 倒是台湾的Python社区有网友说起,并且参会了)。

Planet Python上看到一篇PyCon 2008 notes, 详细地说明了一下他参加的几个主题的内容,推荐!
  • Using Python To Teach Object-Oriented Programming in CS1
  • MPI Cluster Programming with Python and Amazon EC2
  • Applying Expert System Technology to Code Reuse with Pyke
  • Rich UI Webapps with TurboGears 2 and Dojo
  • State of Django
  • High performance Network IO with Python + Libevent
  • Plenary: Twisted announcement: they have a foundation
  • Plenary: You *can* Fool All of the People All of the Time
  • Plenary Keynote: Intellectual Property and Open Source
  • SQLAlchemy 0.4 and Beyond
  • Managing Complexity (and testing)
  • Using Grok to Walk Like a Duck
  • Case Study of Python Application Development Humanized Enso
  • To RE or not to RE Parsing text in Python
  • Plenary: Making Client-Side Python Suck Less
  • Plenary Keynote: Snake Charming the Dragon: the past, present and future of Python and Mozilla
  • Plenary: OLPC Update
  • Consuming HTML
  • nose: testing for the lazy coder
  • Introducing Agile Testing Techniques to the OLPC Project

Firefox 3上Google Reader无法显示内容的问题: Firebug惹的祸

现象: Firefox 3上访问Google Reader时,只显示顶部的一些链接,那个黄色的"loading"就一直不消失,内容也就出不来
原因: 禁用Firebugs扩展即可
定位方法:
  1. 开始看见"loading"一直在,以为跟Google Mail一样,是网速问题导致内容无法显示出来;
  2. 后来逐渐发现Firefox 2上没有问题;
  3. 在Google上搜索"Firefox 3 Google Reader"没有什么有效结果,看来不是使用Firefox 3的人都有这问题
  4. 试验Firefox的"安全模式",正常了,看来是扩展的问题
  5. 对扩展使用折半定位: 先禁用一半扩展,重启Fx,看是否有问题,有问题则将被禁用的扩展缩小一半再试,没问题就将未被禁用的扩展减少一般再试。这样我的20多个扩展,只要5次就可以定位出来了:是Firebug!
  6. 禁用Firebug扩展, 好了

另外,家里的机器上用Firefox 3访问Google Reader就崩溃,不知道为啥,从beta 2到beta 4一直有这个问题(每出一个beta版本我都会试一下)

采用TiddlyWiki搭建blog

前几日一直在琢磨把俺的Blog迁移到这个玩意儿上来,好处在于:
  • 所有文章都在一个网页内, 几百篇文章加起来也没有多大,而且要分多页也很简单
  • 这一个网页可以既是最终发布的地方,也是编撰系统
  • 随便找个能上传网页的地方就可以搭建blog了,万一都没有,在http://www.tiddlyspot.com上申请一个账户也行
  • 丰富的插件,自己想怎么玩就怎么玩
我试验了一下,基本上满意,诸位可以看看初步效果http://bamanzi.tiddlyspot.com/。只是目前没有时间将一篇篇贴过来觉得麻烦,懒得动了。

如果将TiddlyWiki改造成更适合blog的系统,我的一些心得如下:

  • RecentTiddlersPlugin或者WeblogPlugin自动在页面打开时显示最近的文章
  • 采用TagCloudPlugin插件,在MainMenu中添加一个"标签云"
  • TW原本的风格是双击帖子就进入编辑模式,如果你觉得这样不适合于blog系统,可以在选项中将页面设置为网上只读模式,或者采用ReplaceDoubleClick将双击功能改造一下
  • CommentScript能增加留言功能

另外下面这几个插件虽跟blog关系不大,也是应该有的:

  • 这里取得最新的中文翻译,将其作为插件加入,保存后再打开就会变成中文界面了
  • 添加GotoPlugin或者SearchOptionsPlugin,替代原来的搜索功能(原来的搜索会自动打开匹配结果,即使你在只输入了两个字符之后就停顿了一下...)
  • 添加FullScreenPlugin或者ToggleLeftSideBar这类插件(后者其实不是插件,而是借助InlineJavascriptPlugin实现功能的脚本),使得用户可以将文章最大化;添加CollapseTiddlerPlugin或者[FoldHeadingPlugin|http://www.tiddlytools.com/#FoldHeadingsPlugin]] 使得用户可以将文章最小化(可以将帖子折叠起来,只显示标题)

前面说的是对最终页面呈现有用的插件,但还需要东西来帮助我们撰写文章:

  • WikiBarPlugin可以在编辑文章时显示一个工具条(不过IE对CSS支持太差,工具条的下拉菜单显示不出来),免得你记不住那么多wiki语法(不同的wiki语法还不一样:-()——当然,宏还是应该记熟悉的
  • tiddlytools提供的QuickEditPackage也可以提供WikiBar那样的工具条,但我还没搞明白怎么挪用过来:-(
  • TiddlerTweakerPlugin会允许你自行修改每个tiddler的作者、创建时间、修改时间,如果你想迁移你的blog系统肯定用得上

但这几个插件体积都比较大,直接加到你的TW中会导致最后的HTML比较大,加载太慢,而放在网页上对阅读blog的朋友又没有什么作用,这就可以采用将这些插件用外部文件的方式来加载了,LoadExtPlugin就是干这个的(该网站还提供了一个不小的主题包)。

2008年3月6日星期四

TiddlyWiki: 单网页的Wiki, GTD或者blog系统

这几日迷上了TiddlyWiki这个东西, 仅仅一个网页, 却将JavaScript,CSS和DOM的功能发挥到了极致。当年看见Gmail的时候惊叹网页上的东西也可以做得这样易用,而到了TiddlyWiki这里发现Gmail也不算啥了。

简单地说,从名字上可以看出,它具有一些wiki的功能,但它自带条目(它管这叫做tiddler)的管理,点击名称时时显示内容到中间区域——其实这就是一个简单的笔记软件了,并且不用安装任何其他的软件,我以前都用notecase来记录一些琐碎的东西,但现在用不着了。

如果只是这样,还不算什么,但它还有宏、主题、导入、导出等等功能。更强的是跟Firefox, Eclipse这样的东西类似,有一个很好的扩展机制,结果是有太多的插件使得我们可以把它做成一个GTD系统或者blog系统,Blog before you Think这篇文章就介绍了各种变体。

唯一的限制在于这些编辑只能在本地文件上做,网页自身没有机制将内容提交到服务器上去。不过也有网站提供TiddlyWiki服务(http://www.tiddlyspot.com),使得可以将服务保存到服务器,甚至下载到本地,修改完成后再点击网页上一个链接就上传了。

前几日一直在琢磨把俺的Blog迁移到这个玩意儿上来,反正几百篇文章加起来也没有多大。只是一篇篇贴过来觉得麻烦,懒了。诸位可以看看初步效果http://bamanzi.tiddlyspot.com/