`
lovnet
  • 浏览: 6985019 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

闭包的概念 [翻译]

 
阅读更多

解释函数式编程中的闭包概念,非完全翻译自 wiki: closure

文章中使用英文名词,以防止翻译不当和歧义

原文: wiki: closure
译文: 闭包的概念
译者: Breaker <breaker.zy_AT_gmail>

译文


closure 概念

closure 亦称词法闭包 (lexical closure)、函数闭包 (function closure) 或函数值 (function value),是由 一个函数 和 这个函数的 non-local 变量的引用环境 (referencing environment) 组成的实体。这里的 non-local 变量和 C++ 中的 static 和全局变量是不同概念,见 wiki: non-local variable

closure 用途

第一级函数 (first-class function): 函数如同整数和字符串等基本类型一样,作为参数传递、返回值 和 绑定变量名

状态表达 (state representation): closure 在一个函数和一组私有 upvalue 变量之间建立关联关系,多次调用中保持 upvalue 值,并且只能从 closure 函数内访问 upvalue,这些可用在状态式语言中的状态表达范型和信息隐藏

控制结构: 闭包只在被调用时才执行函数,即延迟求值 (delay evaluation),可用来定义控制结构,如 Smalltalk 中的 if 条件分支和 while 循环控制结构都通过 closure 实现

多个 closure 函数用共享环境进行消息传递

实现对象系统: 见 Re: FP, OO and relations. Does anyone trump the others?

upvalue 和引用环境

引用环境绑定在 closure 上的自由变量 (free variable) 或 non-local 名字称为 upvalue,upvalue 的生存期可持续到 closure 的生存期结束

当执行进入 closure 函数时,函数可以访问 closure 绑定的 upvalue,只要 closure 不释放,则调用之间保持 upvalue 的值

在一些语言中,在函数中定义另一个函数时,如果内部函数引用了外部函数的局部变量,则可能产生 closure。运行时,一旦外部函数执行,就会形成 closure,其包含了内部函数的代码 和 其到外部函数所需变量的引用 (upvalue)

closure 和匿名函数

在大多数支持 closure 的语言中,经常用匿名函数来构造 closure,但它们是不同的两个概念

可以认为匿名函数是函数字面量 (function literal),偏向右值和函数体的概念;而 closure 是函数变量 (function value),偏向左值和对象的概念

closure 会保持引用环境,如 upvalue 的当前值,而匿名函数不必如此

closure 的历史

closure 术语最早由 Peter J. Landin 在其 SECD machine 中定义,用以表达式求值中的 environment part 和 control part (1964)

后来 Joel Moses 用 closure 指代 lambda 表达式 其绑定开放的 free variable 被词法环境 (lexical environment) 关闭绑定 (bound in) 时,形成的关闭表达式 (closed expression) 即 closure

后来 Sussman 和 Steele 采用了 closure 概念,并首次在 Scheme 中实现 (1975),以支持词法作用域 (lexically-scoped) 的 first-class function

上面的 lexical environment, lexically-scoped 可以非正式的理解为语言中的作用域

closure 最显著的使用是 ML 和 Lisp 等语言的函数式编程 (functional programming)

传统的命令式语言 (imperative language, e.g. Algol, C, Pascal) 不支持 closure,因为它们不支持 non-local 名字,只有在嵌套函数和匿名函数中才引入此概念,同时它们也不支持 higher-order 函数

现代的带垃圾收集 (GC, garbage collection) 的命令式语言 (Smalltalk, C#) 和 解释性的脚本语言,很多都支持 higher-order 函数和 closure

closure 实现方法

closure 典型的实现方法,采用包含下面两者的一个数据结构:

指向函数代码的指针
函数 lexical environment 的表示结构,如 closure 创建时,函数的可用变量集合及其值

如果语言采用在堆栈上分配局部变量的运行时内存模型,那么很难实现完全的 closure,因为函数返回时会释放局部变量

closure 需要 upvalue 在 enclosing function 即外层函数执行结束后继续保持,因此 upvalue 应该一直保持的内存分配,直到最终不需要时才释放,所以很多支持 closure 的语言都使用 GC

另外,语言也可以选择接受特定使用导致的不确定行为,如 C++ 标准的 lambda 表达式实现提议,见 Lambda Expressions and Closures

Funarg problem (functional argument problem) 说明了在基于堆栈的语言,如 C/C++ 中实现 first class function 的困难

第一版 D 语言,假定程序员知道如何对待从定义作用域中返回后引用无效的 delegate 和局部变量(局部变量在堆栈上分配),此时仍能使用很多 functional pattern,但对于复杂情况需要显式地对变量进行堆分配

第二版 D 解决了这个问题,它检测哪些变量必须存储在堆上,并且执行自动分配。因为 D 的两个版本都使用 GC,所以不需要跟踪传递时变量的使用

在一些使用 immutable data 的严格函数式语言,如 Erlang 中,很容易实现自动内存管理 (GC),因为它们没有变量引用。如在 Erlang 中,所有的变量都在堆上分配,但是它们的引用存储在堆栈上,当函数返回后,引用依然有效,堆清理由增量 GC 完成

ML 中局部变量在堆栈上分配,当创建 closure 时,会将 closure 所需的变量值拷贝进 closure 的数据结构中

Scheme 是类似 ALGOL 的词法作用域系统,带有动态变量和 GC,缺少堆栈编程模型,所以也没有基于堆栈语言的限制,可以直接表达 closure。包含执行代码和环境 free variable 的 lambda 表达式,可在程序中一直保持访问,也可被其它 Scheme 表达式使用

closure 和并发计算 Actor model 中的 Actor 有紧密关系,那里函数 lexical environment 中的值称为 acquaintance。关于 closure 在 并发编程 语言中的一个重要问题是:closure 中的变量是否可更新,如何同步这些更新,Actor 给出一种方案,见 Foundations of Actor Semantics

closure 示例

上面的 closure wiki 解释比较抽象,下面是一个具体的 Javascript closure 示例:

说明:

  1. closure 会绑定 closure 函数和 upvalue,并保持 upvalue 的值
  2. 不同的 closure environment 是不同的绑定,它们的 upvalue 相互独立

[END]

分享到:
评论

相关推荐

    函数式Swift-喵神翻译

    本书首先介绍了函数式编程的基本概念,如纯函数、高阶函数、闭包和柯里化。纯函数是返回值仅依赖于输入参数,不涉及外部状态改变的函数,这有助于确保代码的确定性和可预测性。高阶函数则能够接受函数作为参数或返回...

    The Swift 中文完整翻译版

    此外,还介绍了闭包的概念,闭包是Swift中一种能够捕获和存储其所在上下文中变量值的函数。 第5章:枚举与结构体 讲解了枚举的语法和使用,以及与switch语句的配合。结构体是一种定义数据类型的方式,本章还比较了...

    《离散数学》考试大纲.pdf

    集合的概念与运算、 关系的概念及性质、 关系的闭包运算、 等价关系与划分、 相容关系、 偏 序关系及其哈斯图表示、 偏序集中的特殊元素、 函数、入射、满射、双射、复合函数和逆函 数的概念及其性质;函数与一般...

    描述逻辑手册中文版的第一章和第二章加个人PPT

    - 通过角色的传递性,我们可以计算概念和角色的闭包,找出所有可能的相关个体。 - 如,如果我们知道有 A ⊑ ∃R.B,那么所有A的实例都与B的实例通过R连接。 5. **冲突检测** - 推理系统还可以检查本体中的不一致...

    JavaScript英文翻译

    在学习JavaScript时,理解作用域(全局和局部)和闭包的概念至关重要。此外,原型继承是JavaScript中实现面向对象编程的一种方式,而ES6引入的类和模块系统则让JavaScript的面向对象编程更加符合传统的类继承模型。 ...

    Apple Swift官方原版中文翻译资料,非常好

    这份"Apple Swift官方原版中文翻译资料"涵盖了Swift语言的基础到进阶内容,包括但不限于变量、常量、类型推断、控制流、函数、类与结构体、枚举、协议、错误处理、泛型、闭包、Optionals、数组、字典等核心概念。...

    JavaScript语言精粹(翻译版+英文版)

    这本书旨在帮助读者掌握JavaScript的核心概念,包括变量、数据类型、函数、对象、闭包、原型链等基础内容。同时,它也深入探讨了错误处理、性能优化、DOM操作以及事件处理等实践技巧。通过阅读这本书,读者可以了解...

    The Swift Programming Language中文完整版(CocoaChina精校)

    闭包部分解释了闭包表达式、Trailing闭包、闭包捕获以及闭包作为引用类型的概念。 9. 枚举 讲解了枚举的语法、如何匹配枚举值以及switch语句的使用、关联值以及原始值的应用。 10. 类和结构体 这部分深入探讨了类...

    CS61A 教材 Composing Programs 的中文翻译.zip

    2. **函数式编程**:强调函数作为一等公民的概念,讲解高阶函数、闭包和函数组合,这是JavaScript中实现模块化和抽象的关键。 3. **递归**:深入探讨递归算法,它是解决复杂问题的一种强大工具,常用于树形结构和图...

    离散数学结构

    关系与有向图部分引入了笛卡儿积、关系运算、传递闭包等概念,并通过WarshaU算法等介绍传递闭包的计算方法。函数章节从基础的函数定义出发,探讨了函数的增长、置换函数,并与计算机科学中的函数概念相结合。 序...

    Python精要参考(第二版)_翻译pdf

    《Python精要参考(第二版)_翻译pdf》是Python编程领域的一本重要参考资料,它深入浅出地介绍了Python语言的核心概念、语法结构以及常用库的使用。这本书的翻译版为中文,使得国内的Python学习者能够更加方便地理解和...

    翻译] Lua v5.1.4手册

    函数定义使用`function`关键字,支持匿名函数和闭包。 4. **环境与作用域**:Lua的环境是通过表实现的,全局环境是一个特殊的表。`_G`全局变量指向这个环境。局部变量的作用域仅限于其定义的块。 5. **元表...

    ANSI Common Lisp 中文翻译版

    - **第六章:函数(Functions)**:深入探讨 Lisp 中函数的概念、定义方法以及高级用法,如高阶函数和闭包。 - **第七章:输入与输出(Input and Output)**:介绍了 Lisp 中处理文件和网络通信的方法。 - **第八...

    swift3中文文档.pdf

    文档内容涵盖广泛,从基本概念如变量、常量、类型系统、集合类型、控制流,到进阶主题如函数、闭包、枚举、类、协议和继承。每一部分都深入浅出地讲解了Swift 3.0的关键概念和用法,是学习和巩固Swift编程技能的宝贵...

    Groovy(2007,2,21)

    这个文档由屈忠慰在2007年2月21日翻译,旨在介绍Groovy的基本概念和特性,帮助开发者快速入门。 Groovy的设计目标是简化Java开发,提供更简洁、更易于理解的语法。其主要特点包括: 1. **动态类型**:Groovy允许...

    convex optimization theory_bersekas

    对于凸函数而言,其相对内部与闭包的概念,是分析和理解函数全局性质的重要工具。 凸分析中的运算包括加法、数乘等操作,这些操作在凸集和凸函数上的结果依然是凸的。此外,还有用于描述凸集和凸函数特性的定理和...

    Lua_API中文翻译高清版

    Lua API中文翻译高清版是针对编程语言Lua的官方应用程序接口(API)的详细中文文档,旨在帮助中国开发者更好地理解和使用Lua。Lua是一种轻量级、高效、可扩展的脚本语言,广泛应用于游戏开发、系统配置、嵌入式系统...

    Swift 中文版帮助手册(The Swift Programming Language)

    《Swift 中文版帮助手册(The Swift Programming Language)》是由CocoaChina翻译整理的,这是一份为初学者量身打造的Swift语言学习资料,旨在帮助读者快速掌握Swift编程语言的基础知识和核心技术。Swift是苹果公司...

    rust book 中文翻译

    ### Rust Book中文翻译知识点概述 #### 一、Rust编程语言简介 - **Rust的特点**:Rust是一种系统级编程语言,强调安全性与性能。它通过编译时的安全检查来确保内存安全,同时避免了运行时开销,使得Rust能够在其他...

Global site tag (gtag.js) - Google Analytics