`
taylorqt
  • 浏览: 14964 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

[zz] Closure

阅读更多
Martin Fowler:闭包
关键字:   NULL     Martin Fowler:闭包
原著:Martin Fowler  http://martinfowler.com/bliki/Closures.html

翻译:huangpuzhuang.com>

http://www.ruby-cn.org/

另外一片文章总结了各种语言实现的本文中的例子。

闭包(Closures)在各种语言中的例子

2004/11/23

本文地址:http://www.ruby-cn.org/articles/closures.html


    随着人们对动态语言兴趣的日益浓厚,越来越多的人都遇到了闭包(Closures )和或块(Blocks)等概念。有着C/C++/Java/C#等语言背景的人因为这些语言本身没有闭包这个概念,所以可能不太了解闭包。本文将简单的介绍一下闭包的概念,那些有大量支持闭包语言编程经验的人也许觉得本文不会太有意思。

    闭包的概念已经提出很长时间了。我第一次碰到这它是在smalltalk中,那时候还叫做块(blocks)。Lisp语言中用的很多。Ruby中也有同样的功能-这也是Ruby用户喜欢Ruby的一个原因。

    本质上来说,一个闭包是一块代码,它们能作为参数传递给一个方法调用。我将通过一个简单的例子来阐述这个观点。假设我们有一个包含一些雇员对象的列表,然后我想列出职位为经理的员工,这样的员工可以通过IsManager判断。在C#里,我们可能会写出下面类似的代码:
  public static IList Managers(IList emps) {
    IList result = new ArrayList();
    foreach(Employee e in emps)
      if (e.IsManager) result.Add(e);
    return result;
  }

    在一种支持闭包的语言中,比如Ruby,我们可以这样写:
  def managers(emps)
return emps.select {|e| e.isManager}
  end
 

    select是Ruby中定义的集合结构中的一个方法,它接受一个block,也就是闭包,作为一个参数。在Ruby中,闭包写在一对大括号中(不止这一种方法,另一种为do .. end)。如果这个块也接受参数,你可以将这些参数放到两个竖线之间。select方法循环迭代给定的数组,对每个元素执行给定的block,然后将每次执行block返回true的元素组成一个新的数组再返回。

    现在,如果你是C程序员你也许要想,通过函数指针也可以实现,如果你是JAVA程序员,你可能回想我可以用匿名内类来实现,而一个C#者则会想到代理(delegate)。这些机制和闭包类似,但是它们和闭包之间有两个明显得区别。

    第一个是形式上的不同(The first one is a formal difference)。闭包可以引用它定义时候可见的变量。看看下面的方法:
def highPaid(emps)
threshold = 150
return emps.select {|e| e.salary > threshold}
end
 

    注意select的block代码中引用了在包含它的方法中的局部变量,而其它不支持真正闭包的语言使用其它方法达到类似功能的方法则不能这样做。闭包还允许你做更有趣的事情,比如下面方法:
def paidMore(amount)
return Proc.new {|e| e.salary > amount}
end

    这个方法返回一个闭包,实际上它返回一个依赖于传给它的参数的闭包。我可以用一个参数创建一个这样的方法,然后再把它赋给另一个变量。
highPaid = paidMore(150)

    变量 highPaid 包含了一段代码(在Ruby中是一个Proc对象),这段代码将判断一个对象的salary属性是否大于150。我们可以这样使用这个方法:
john = Employee.new
john.salary = 200
print highPaid.call(john)
 

      表达式highPaid.call(john)调用我之前定义的代码,这时候此代码中的amount已经在创建这方法的时候绑定为150。即使现在我执行print 的时候,150已经不在它的范围内了,但是amount和150之间的绑定依然存在。

    所以,闭包的第一个关键点是闭包是一段代码加上和定义它的环境之间的绑定(they are a block of code plus the bindings to the environment they came from)。这是闭包和函数指针等其它相似技术的不同点(java匿名内类可以访问局部变量,但是只有当这些内类是final的时候才行)。

    第二个不同点不是定义形式的不同,但是也同样重要。(The second difference is less of a defined formal difference, but is just as important, if not more so in practice)。支持闭包的语言允许你用很少的语法去定义一个闭包,尽管这点可能不是很重要的一点,但我相信这点是至关重要的-这是使得人们能很自然的使用闭包的关键点。看看Lisp,Smalltalk和Ruby,闭包遍布各处-比其它语言中类似的使用多很多。绑定局部变量是它的特点之一,但我想最大的原因是使用闭包的语法和符号非常简单和清楚。

    一个很好的相关例子是从Smalltalk程序员到JAVA程序员,开始时很多人,包括我,试验性的将在Smalltalk中使用闭包的地方在Java中使用匿名内类来实现。但结果使得代码变得混乱难看,所以我们不得不放弃。

   我在Ruby经常使用闭包,但我不打算创建Proc对象,然后传来传去。大多数时间我用闭包来处理前面我提到的select等基于集合对象的方法。闭包另一个重要用途是'execute around method',比如处理一个文件:
File.open(filename) {|f| doSomethingWithFile(f)}

   这里open方法打开一个文件,然后执行给定的block,然后关闭它。这样处理非常方便,尤其是对事务(要求commit或者rollback),或者其它的你需要在处理结束时候作一些收尾处理的事情。我在我的xml文档转换中广泛使用这个优点。

   闭包的这些用法显然远不如用Lisp语言的人遇到的多,即使我,在使用没有闭包支持的语言的时候,也会想念这些东西。闭包就像一些你第一眼见到觉得不怎么样的东西,但你很快就会喜欢上它们。
其它语言例子

Joe Walnes在blog中提供了 closures in the next version of C#。这个例子是静态类型语言的,基于delegate,且需要delegate关键字。

更新: Ivan Moore提供类类似的 Python 的例子

更新: Vadim Nasardinov 让我知道了来自Guy Steeleled的 closures in Java 这个有趣的珍闻。


 译者注:如你想知道上面例子中文件对象是怎么自己关闭的,请看http://blog.csdn.net/ruby_cn/archive/2004/11/23/192588.aspx,希望可以找到答案。翻译的不好,请多原谅。欢迎交流。括号之中的英语实在是不知如何很好翻译,所以保留了下来。
分享到:
评论

相关推荐

    closure闭包

    在编程语言理论中,"closure"一词通常指的是“闭包”,它是一个非常重要的概念,尤其是在函数式编程和动态类型语言中。闭包是函数和与其相关的引用环境(即变量的值)的组合,这个组合使得函数能够记住它被定义时的...

    Closure Linter完整安装包

    Closure Linter是一款强大的静态代码分析工具,主要用于检查JavaScript代码的质量,确保代码符合Google的 Closure编程风格指南。这个压缩包提供了一个完整的Closure Linter安装包,包括必要的依赖和安装说明,以便...

    closure-compiler-v20171112.jar

    Closure Compiler是Google开发的一款强大的JavaScript代码优化工具,其主要功能是对JavaScript代码进行压缩和混淆,以提高代码的运行效率和安全性。"closure-compiler-v20171112.jar"是该编译器的一个特定版本,发布...

    closure-library-master

    "closure-library-master" 是一个与 Google 的 Closure Library 相关的开源项目。Closure Library 是一个广泛使用的 JavaScript 库,尤其在构建大型、高性能的 Web 应用程序时非常有用。这个库提供了大量的实用工具...

    Closure-Table-ClosureTable.rar

    Closure Table 是数据库设计中一种处理层次结构数据的方法,主要用于存储具有层级关系的数据,例如组织架构、类别层次等。在这个名为 "Closure-Table-ClosureTable.rar" 的项目中,开发者使用了Spring、SpringMVC...

    Closure The Definitive Guide

    If you're ready to use Closure to build rich web applications with JavaScript, this hands-on guide has precisely what you need to learn this suite of tools in depth. Closure makes it easy for ...

    google closure

    Google Closure 是一个强大的JavaScript开发工具集,由Google开源并维护。这个框架包含了多个部分,旨在帮助开发者编写高质量、高性能的JavaScript代码。Closure的核心组件包括: 1. **Closure Library**:这是一个...

    closure library 模块化的javascript库

    Closure Library是Google开发的一个强大的、模块化的JavaScript库,旨在提供高效、可维护的代码解决方案。这个库被设计为可跨浏览器、跨平台使用,确保在各种JavaScript环境中的一致性。Closure Library的核心理念是...

    前端开源库-closure-loader

    **Closure Loader - 前端开发的利器** Closure Loader是一个专为前端开发者设计的开源工具,主要用于处理Google闭包库(Closure Library)的依赖管理。这个加载器是Webpack的一个插件,它允许开发者在Webpack构建...

    用谷歌的closure-compiler + maven-antrun-plugin

    标题中的“用谷歌的closure-compiler + maven-antrun-plugin”表明了本文将探讨如何结合Google的Closure Compiler工具和Maven的Antrun插件来优化JavaScrip项目。Closure Compiler是一款强大的JavaScript代码压缩器,...

    loop_closure_闭环检测_loopclosure_

    在机器人定位和导航领域,闭环检测(Loop Closure)是一个至关重要的技术,它涉及到传感器数据处理、地图构建(SLAM:Simultaneous Localization and Mapping)以及机器学习等多个方面。标题"loop_closure_闭环检测_...

    Closure: The Definitive Guide

    在给定文件内容中提及的《Closure: The Definitive Guide》是由Michael Bolin撰写,涵盖了Google开发的Closure工具集,这个工具集包括了Closure Library、Closure Templates、Closure Compiler以及Closure Testing ...

    Closure编译器的纯JavaScript版本最高级的构建工具

    Closure编译器是Google开发的一款强大的JavaScript优化工具,它的纯JavaScript版本为开发者提供了一种高效、先进的代码构建方案。此工具旨在提升JavaScript代码的质量、性能和可维护性,通过压缩、优化以及处理代码...

    js压缩工具Google Closure Compiler

    **谷歌闭包编译器(Google Closure Compiler)详解** 谷歌闭包编译器(Google Closure Compiler)是一款强大的JavaScript代码优化工具,由Google开发并维护。它通过对JavaScript代码进行语法分析和压缩,帮助开发者...

    Google Javascript Closure Compiler

    closure-compiler-v20170521.jar,以及一个.chm使用说明:‘Getting Started with the Closure Compiler Application’,‘Advanced Compilation and Externs’,‘Understanding the Restrictions Imposed by the ...

    使用Google Closure Compiler js压缩

    **使用Google Closure Compiler进行JavaScript压缩** Google Closure Compiler是一款强大的JavaScript优化工具,由Google开发,它能够对JavaScript代码进行压缩、优化和格式化,以提高网页加载速度和减少网络带宽...

    closure dependency not found解决包

    当我们从github上下载了blockly之后,打卡demos下的index.html时,选择blockly-developer-tools时会弹出一个对话框(大体内容是closure dependency not found),此时我们需要下载这个文件,解压并且命名为closure-...

    Closure Compiler exe

    Closure Compiler exe 根据[在项目中使用Google Closure Compiler](http://www.cnblogs.com/JeffreyZhao/archive/2009/12/09/ikvm-google-closure-compiler.html)

Global site tag (gtag.js) - Google Analytics