zoukankan      html  css  js  c++  java
  • Lua 函数、闭包、尾调用总结


    《lua 程序设计》在线阅读:http://book.luaer.cn/


    1.函数

    函数有两种用途:
    • 完成指定的任务,这种情况下函数作为调用语句使用;
    • 计算并返回值,这种情况下函数作为赋值语句的表达式使用。

    1.1 语法

    function func_name (arguments-list)
        statements-list;
    end;
    示例

    function foo (x) return 2*x end
    foo = function (x) return 2*x end
    从上面我们可以看出lua函数定义实际上是一个赋值语句,将类型为function的变量赋给一个变量,需注意:

    • 调用函数的时候,如果参数列表为空,必须使用()表明是函数调用。
    • 当函数只有一个参数并且这个参数是字符串或者表构造的时候,()可有可无,例如
    print "Hello World"      <-->       print("Hello World")

    1.2 返回值

    lua函数可以返回多个值
    function foo0 () end                   -- returns no results
    function foo1 () return 'a' end        -- returns 1 result
    function foo2 () return 'a','b' end    -- returns 2 results
    需注意返回多个值是:
    1. 多返回值的函数必须是作为表达式最后一个参数,否则只返回一个值
    2. 接收的话不足补nil,超出舍去,如
    x,y = foo2()             -- x='a', y='b'
    x,y = foo1();            -- x = 'a', y= nil 
    x = foo2()               -- x='a', 'b'舍去
    x,y = foo2(), 20         -- x='a', y=20
    另外,括号可以强制返回一个值
    print((foo2()))      --> a

    1.3 可变参数

    • 可变参数用...来表示
    • Lua将函数的可变参数放在一个叫arg的表中,除了参数以外,arg表中还有一个域n表示参数的个数。
    function fn(name,nick,...)
        print(name,nick)      -- 一撮毛  大帅锅
      for i,v in ipairs(arg) do
           print(arg[i])      -- 1,2,3,4
        end
    end
    fn("毛毛","大帅锅",1,2,3,4);  -- name="毛毛",nick="大帅锅",arg={1,2,3,4; n = 4}
    

    2.函数闭包

    当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。
    先看如下代码:

    function fn()
        local i = 0
        return function()     -- 注意这里是返回函数的地址,不是执行
           i = i + 1
            return i
        end
    end
    
    c1 = fn()           -- 接收函数返回的地址
    print(c1())  --> 1          --c1()才表示执行
    print(c1())  --> 2
    如上,调用c1()时,fn函数明显已经返回,lua闭包闭包思想正确处理这种情况:

    • 我们称i为从c1的外部局部变量(external local variable)或者upvalue。
    • 简单的说,闭包是一个函数以及它的upvalues
    如果我们再次调用fn,将创建一个新的局部变量i:

    c2 = fn()
    print(c2())  --> 1
    print(c1())  --> 3
    print(c2())  --> 2

    3.函数尾调用

    • 尾调用是一种类似在函数结尾的goto调用。
    • 当函数最后一个动作是调用另外一个函数时,我们称这种调用尾调用。

    例如:

    function f(x)
        return g(x)  -- 类似于goto g(x)函数的地址
    end

    • 尾调用不需要使用栈空间,因此尾调用递归的层次可以无限制的。

    例如下面调用不论n为何值不会导致栈溢出。

    function foo (n)
        if n > 0 then return foo(n - 1) end
    end
    需要注意的是:必须明确什么是尾调用。
    一些调用者函数调用其他函数后也没有做其他的事情但不属于尾调用。比如:

    function f (x)
        g(x)
        return
    end
    上面这个例子中f在调用g后,不得不丢弃g地返回值,所以不是尾调用,同样的下面几个例子也不时尾调用:
    return g(x) + 1      -- 还需+1
    return x or g(x)     -- 还需比较
    return (g(x))        -- 还需调整为一个返回值





  • 相关阅读:
    关于SQL Server系统数据库详解
    如何删除发布服务器distribution
    SQL Server如何删除多余tempDB文件
    SQL Server 中用While循环替代游标Cursor的解决方案
    理解性能的奥秘——应用程序中慢,SSMS中快(4)收集解决参数嗅探问题的信息
    第十六章——处理锁、阻塞和死锁(3)——使用SQLServer Profiler侦测死锁
    第十六章——处理锁、阻塞和死锁(2)——侦测阻塞和阻塞查询
    降级与熔断
    浅淡缓存
    小P的架构生活(下)
  • 原文地址:https://www.cnblogs.com/fzll/p/3954571.html
Copyright © 2011-2022 走看看