• 函数式编程里的Closures闭包

    函数式和面向对象的结合
    服务器君一共花费 80.024 ms 进行了 3 次数据库查询,努力地为您提供了这个页面。
    广告很萌的

    到此我们已经讨论了纯函数式语言——实现了 λ 演算又不包括与丘奇形式系统矛盾的语言——里的特性,可是还有很多在 λ 演算框架之外的函数语言的有用特征。虽然一个公理系统的实现可以让我们象数学表达式那样思考程序但它未必是实际可行的。

    许多语言选择去合并一些函数式的元素而没有严格的坚持函数式的教条。很多像这样的语言(如 Common Lisp)不要求变量是 final 的——可以对其修改。他们还不要求函数只依赖于其参数——允许函数访问外部状态。但这些语言也的确包含着函数式的特征——如高阶函数,在非纯粹的函数式语言里传递函数作为参数和限制在 λ 演算系统中的作法有些不同,它需要一种常被称为词法闭包(lexical closure)的有趣特性。下面我给出几个例子。记住,这里变量不再是 final 的,函数可以引用其作用域外的变量:

    Function makePowerFn(int power) {
        int powerFn(int base) {
            return pow(base, power);
        }
        return powerFn;
    }
    
    Function square = makePowerFn(2);
    square(3); // returns 9
    

    函数 make-power-fn 返回了一个函数,它有一个参数,并对这个参数进行一定阶的幂运算。如果对 square(3) 求值会有什么结果?变量 power 不在 powerFn 的作用域中,因为 makePowerFn 已经返回它的栈桢而不复存在。那么 square 如何工作?一定是这个语言以某种方式将 power 的值保存了起来以便 square 使用。如果我们再新建一个函数 cube,用来计算参数的立方又会怎样?运行环境必须存储两个 power 的拷贝,每个我们用 make-power-fn 生成的函数都用一个拷贝。保存这些值的现象就被称为 closure。Closure 不只保存宿主函数的参数,例如 closure 可能会是这样:

    Function makeIncrementer() {
        int n = 0;
    
        int increment() {
            return ++n;
        }
    }
    
    Function inc1 = makeIncrementer();
    Function inc2 = makeIncrementer();
    
    inc1(); // returns 1;
    inc1(); // returns 2;
    inc1(); // returns 3;
    inc2(); // returns 1;
    inc2(); // returns 2;
    inc2(); // returns 3;
    

    运行时已保存了 n,所以递增器可以访问它,而且运行时为每个递增器都保存了一份 n 的拷贝,即使这些拷贝本应在 makeIncrementer 返回时消失。这些代码被如何编译?closure 在底层是如何工作的?很幸运,我们可以去幕后看看。

    常识会很有帮助,首先应注意到的是,局部变量的生命周期不再由简单的作用域限定,而变成不确定的,从而可以得出结论它们不能保存在栈上,而必须保存在堆上。这实际上不比存储在栈上慢,因为一旦引入了垃圾回收器,内存分配就成为了一个 O(1) 的操作。这样一来,closure 的实现就象我们前面讨论的函数一样了,只是它还有一个指向周围变量的引用。

    class some_function_t {
        SymbolTable parentScope;
        // …
    }
    

    当一个 closure 引用了一个不在其作用域的变量时,它会在其祖先作用域中查找这个引用,就是这样!Closure 将函数式和面向对象的世界紧密结合。当你创建了一个包含了一些状态的类并把它传到别处时,考虑一下 closure。Closure 就是这样在取出作用域中的变量的同时创建“成员变量”,所以你不必亲自去做这些。

    关于函数式编程,本文作了浅显地讨论。有时候一次粗浅的涉猎可能会进展为重大的收获,对我们来说这是好事。将来我还计划写写 category 理论、monad、函数式数据结构、函数式语言中的类型(type)体系、函数式并发、函数式数据库等等,可能还有很多。如果我得以(在学习的过程中)写出了上述诸多主题中的一半,我的生命就会完整了。还有,Google 是我们的朋友。

更多 推荐条目

Welcome to NowaMagic Academy!

现代魔法 推荐于 2013-02-27 10:23   

本章最新发布
随机专题
  1. [数据库技术] 无限级分类数据表设计 4 个条目
  2. [移动开发] Android属性系统Property 9 个条目
  3. [Linux操作系统] CentOS上使用EPEL Repository 2 个条目
  4. [搜索引擎优化] 百度搜索引擎优化指南 3 个条目
  5. [软件工程与项目管理] 浏览器初步介绍 8 个条目
  6. [智力开发与知识管理] 整体性学习策略 9 个条目
  7. [移动开发] 从代码角度去认识 Handler 4 个条目
  8. [数据结构] 图的定义 1 个条目
  9. [PHP程序设计] PHP中的Hash算法 3 个条目
  10. [Python程序设计] Tornado背景知识介绍 4 个条目
  11. [软件工程与项目管理] 浏览器的HTML解析器 8 个条目
  12. [PHP程序设计] fsockopen,curl与file_get_contents 12 个条目
窗口 -- [协会]