lua语言中的函数概念

来源:互联网 发布:linux驱动模块编译 编辑:程序博客网 时间:2024/06/05 02:46


1. 不同于C,lua中的函数是一种first-class-value,这意味着:
            lua中的函数可以视作一种"值"存储到变量或table中;
            可以作为其他函数的实参;
            可以作为其他函数中的返回值;
            可以嵌套在其他函数中被构造创建,而无需在设计阶段就定义好.
  
2. lua中的函数本身其实都是没有名字的,也就是说通常讨论的函数名(比如print),实际不过是持有某个函数的变量.
   所以,lua中函数的标准定义形式其实是:
            var = function (x) <body> end
   也就是说,一个函数定义其实就是一条赋值语句,这条语句首先是构造一种类型为"函数"的值,然后将这个值赋给一个变量

3. 跟其他大部分语言一样,lua遵循"词法域"(即静态作用域)的原则,又因为lua函数是一种first-class-value,所以才有了闭包(closure)的概念:
            一个闭包就是一个函数加上构造该函数时所需的所有"非局部的变量"(non-local variable)

   一个闭包的典型例子如下:
            function newCounter ()
                local i = 0
                return function ()  -- 匿名函数,也就是闭包
                    i = i + 1
                    return i
                end
            end
            c1 = newCounter()
            c2 = newCounter()
            print(c1)   -- 1
            print(c1)   -- 2
            print(c2)   -- 1
   这个例子中,变量i对于匿名函数来说,既不是全局变量,也不是局部变量,所以就被称为了"非局部的变量";
   调用函数newCounter的过程,其实就是创建一个闭包的过程;
   这里要注意一点,函数名不带括号赋值给一个变量,其实是表示共同持有某个函数,而函数名带括号赋值给一个变量,其实是表示首先调用该函数,然后将该函数的返回值赋值给变量;
   所以以上例子中,c1和c2是同一个函数所创建的两个独立的闭包,也就是说,它们各自拥有独立的i

4. lua函数中存在一种"尾调用"概念:
            当一个函数的最后一个动作是调用另外一个函数,并且包含了关键字"return",那么这条调用就是该函数的尾调用。
   利用这种"尾调用"现象,lua实现了"尾调用消除"机制,原理就是:
            调用函数时,会在内存中形成一个"调用记录",主要保存调用位置和内部变量信息,经过多次嵌套调用函数之后,内
            存中就会堆叠这些"调用记录",形成一个"调用栈"。由于"尾调用"是所在函数的最后一步操作,一旦开始执行"尾调
            用"的函数,外层函数的调用记录就不会再用到,所以就直接释放这个调用记录,然后再写入"尾调用"的函数的调用
            记录即可。
   这种"尾调用消除"机制的意义很明显,那就是如果所有嵌套的函数都符合"尾调用",那么真个嵌套调用的过程中,调用记录同时只会有一项,这就大大节省了内存空间。
   一个典型的应用例子就是"尾递归",调用以下函数时,传入任何数字都不会造成栈溢出:
            function foo (n)
                if n > 0 then
                    return foo (n - 1)
                end
            end
   递归非常耗费内存,因为每次执行递归函数,就要往内存中增加一条调用记录,所以很容易发生"栈溢出"错误。但对于"尾递归"来说,由于同一时刻只会存在一个调用记录,所以永远不
   会发生"栈溢出"问题。
  
           


原创粉丝点击