• 函数式编程相关概念


    Java 8 引入了 lambda 表达式,以及函数式编程风格。在了解函数式编程过程中,做了些笔记,摘录于本文。

    嵌套函数( Nested Function )

    1. 嵌套函数,是指在另一个函数里面定义的一个函数。外层的函数,这里简称为外层函数。

    2. 函数的嵌套可以是多层嵌套。嵌套函数可以看到其全部的外层函数的非局部变量。在实际程序中,嵌套的层数一般很少。下面是一个三层嵌套的例子, innerOfInner 也可以访问在 outer 函数体重定义的变量 x 。

    function outer(){
        var x = 1;
        function inner(){
            x += 1;
            console.log(x);
            function innerOfInner(){
                x += 10;
                console.log(x);
            }
            return innerOfInner;
        }
        return inner;
    }

    3. 嵌套函数对非局部变量拥有读和写的权限。

    4. 如果一个嵌套函数可以逃离外层函数,例如函数是第一公民,并且内嵌的函数被传到另外一个函数作为参数或者被当做返回值,那么,就会产生一个闭包 ( closure ),通过调用逃离的函数,可以访问函数的原本的环境变量。此时,外层函数的框架 ( frame )会继续存在,直到所有指向此框架的闭包消失。闭包所指向的非局部变量会从栈内存被移到堆内存。

    5. Javascript 支持嵌套函数。Java 通过 Lambda 表达式,内部类,匿名类来间接支持内置函数。

    例子,add 是外层函数,plus 是嵌套函数。counter 对于 add 来说是局部变量,对于 plus 来说则是非局部变量 ( non-local variable )。在一个外层函数 add 的函数体里面,定义了一个嵌套函数 plus ,然后调用嵌套函数,并返回结果。

    function add() {
        var counter = 0;
        function plus() {counter += 1;}
        plus();    
        return counter; 
    }

    非局部变量( non-local variable )

    1.非局部变量其实是相对的一个称谓,是指既不是局部又不是全局的变量。这个称谓一般用于内嵌的函数,或者匿名函数的上下文当中。

    2. 在编程语言中,实现非局部变量比较困难,这也导致了嵌套函数、匿名函数高阶函数头等函数等功能难以实现。 

    3. 如在上面第 4 点中提到,当嵌套函数被逃离外层函数时,一个闭包就会被产生,并被用于定位非局部变量。当外层函数返回内嵌函数时,外层函数执行完毕,从栈上被弹出,非局部变量也会从栈上消失。但是非局部变量仍然被内存函数引用,所以需要在堆上给他们重新分配内存。这样,非局部变量的生命周期就会长于定义它的外层函数。

    非局部变量例子简单例子,参照嵌套函数中 add / plus 的代码以及解释。

    闭包 ( Closure )

    1. 在操作中,闭包是指一条记录,存储着一个函数和它的环境变量。这个函数既可以是有名函数,也可以是匿名函数。

    下面例子中,第一个闭包的函数原来是一个有名函数,而第二个闭包的函数原来是匿名函数。

    function f(x) {
        function g(y) {
            return x + y;
        }
        return g; 
    }
    
    function h(x) {
        return function(y) { 
            return x + y 
        }
    }
    
    var ff = f(3);
    ff(5);     // return 8;
    var hh = h(3);
    hh(5);    // return 8;

    闭包可以直接被使用,而不用赋值给其他变量,此时称其为匿名闭包,如下。

    f(3)(5);   // return 8

    2. 原来的嵌套函数例子中,内嵌的函数在外层函数体内被执行,如果外层函数返回嵌套函数,则产生了一个闭包。见下面例子。

    function add() {
        var counter = 0;
        function plus() {
            counter += 1;
            return counter;
        }
        return plus; 
    }

     

    参考资料

    Nested function, wikipedia 

    Non-local variable, wikipedia

    Closure (computer programming), wikipedia

  • 相关阅读:
    P2422 良好的感觉
    拉格朗日插值
    C# 中的委托和事件(详解)
    异步委托
    ManualResetEvent详解
    快速理解C#高级概念事件与委托的区别
    拉格朗日多项式
    oracle 插入一个从别处查询获得字段的值
    decode和nvl的用法
    C#将像素值转换为图片
  • 原文地址:https://www.cnblogs.com/TonyYPZhang/p/5676761.html
Copyright © 2020-2023  润新知