• Lua学习笔记(三):函数和闭包


    函数

    lua的函数以function关键字开始,后跟函数名称和参数,最后以end结束,我们看一个简单的函数定义:

    1 function foo()
    2     --do something
    3 end
    4 
    5 function add(a, b)
    6   return a + b
    7 end

    在载入脚本时,函数不会执行,仅仅是会被载入内存和名称关联起来。

    另外需要注意的是,调用的函数必须是在代码上方进行了定义的函数,否则运行时会报错,如下:

    1 print(add(5, 10))--运行时这里会报错, 因为 add 还没有被载入到内存
    2 
    3 function add(a, b)
    4   return a + b
    5 end
    6 
    7 print(add(5, 10))--正常调用

    参数

    在调用函数时,也需要将对应的参数放在一对圆括号中,即使调用函数时没有参数,也必须写出一对空括号。对于这个规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字符串或table构造式,那么圆括号便可以省略掉:

    1 print "hello1"
    2 print("hello2")
    3 
    4 function foo(a)
    5   print(a)
    6 end
    7 
    8 foo {1, 2, 3, 4}
    9 foo({1, 2, 3})

    函数的参数可以看做该函数体内的一个局部变量,调用函数时提供的实参数量可以与形参数量不同。Lua会自动调整实参的数量,以匹配参数表的要求,若“实参多余形参,则舍弃多余的实参;若实参不足,则多余的形参初始化为nil”:

    1 function foo(a, b, c)
    2   print(a, b, c)
    3 end
    4 
    5 foo(100, 200, 300, 400)--100  200 300
    6 foo(100, 200)--100  200 nil
    7 foo()--nil  nil nil

    变长参数

    使用“...”来定义参数,Lua会在函数中定义一个名为arg的table对象来保存传递的所有参数,如下:

     1 function foo(...)
     2   --arg.n 可以取得参数的长度
     3   print("params length: ", arg.n)
     4   --打印出所有的参数及其类型
     5   for i = 1, arg.n do
     6     print("param index: ", i, ", param value: ", arg[i], ", param type: ", type(arg[i]))
     7   end
     8 end
     9 
    10 foo()
    11 foo(1, 2, 3)
    12 foo("abc", 3.14, true, {1, 2, 3})

    返回值

    使用return可以返回值:

    1 function add(a, b)
    2   return a + b
    3 end
    4 
    5 num = add(100, 200)
    6 print(num)--300

    Lua还支持返回多个值,返回值多余接收值,则舍弃多余的返回值;若返回值不足,则多余的接收值初始化为nil,和参数调用情况一直:

     1 function foo(a, b)
     2   return a + b, a * b, a - b
     3 end
     4 
     5 num1, num2, num3 = foo(100, 200)
     6 print(num1, num2, num3)--300  20000 -100
     7 
     8 num1, num2, num3, num4 = foo(100, 200)
     9 print(num1, num2, num3, num4)--300  20000 -100  nil
    10 
    11 num1, num2 = foo(100, 200)
    12 print(num1, num2)--300  20000
    13 
    14 num1 = foo(100, 200)
    15 print(num1)--300

    深入了解Lua的函数

    在Lua中,函数与其它传统类型的值具有相同的权利。函数可以存储到变量或table中,也可以作为实参传递给其它函数,还可以作为其它函数的返回值。在Lua中有一个容易混淆的概念是,函数与所有其它值一样都是匿名的,即它们都没有名称。当讨论一个函数名时,实际上是在讨论一个持有某函数的变量,比如下面的两个函数声明方式虽然不一样但实际上在Lua看来都是一致的:

    1 function foo1()
    2   --do sometging
    3 end
    4 
    5 foo2 = function()
    6   --do sometging
    7 end

    局部函数

    实际上,一个函数定义实际就是一条语句(更准确地说是一条赋值语句),这条语句创建了一种类型为“函数”的值,并将这个值赋予一个变量。由于函数在Lua中就是一个普通的值,所以不仅可以将其存储在全局变量中,还可以存储在局部变量甚至table的字段中:

     1 obj = {}
     2 obj.add = function(a, b)
     3   return a + b
     4 end
     5 obj.subtract = function(a, b)
     6   return a - b
     7 end
     8 
     9 print(obj.add(100,200))
    10 print(obj.subtract(200,123))

    再看一个例子:

     1 do
     2   local function add(a, b)
     3     return a + b
     4   end
     5   local function subtract(a, b)
     6     return a - b
     7   end
     8   
     9   print(add(100,200))
    10   print(subtract(200,123))
    11 end
    12 
    13 print(add(100,200))--超出作用域, 报错
    14 print(subtract(200,123))--超出作用域, 报错

    闭包

    闭包是由函数和与其相关的引用环境组合而成的实体。我们可以简单的理解为:子函数可以使用父函数中的局部变量,这种行为就叫做闭包。下面我们看一个经典的闭包例子:

     1 function closure()
     2   local i = 0--注意 i 被返回的函数使用
     3   return function()
     4     i = i + 1
     5     return i
     6   end
     7 end
     8 
     9 c1 = closure()--函数作用域已经结束, 但是由于闭包的原因, i 仍然被保留了下来
    10 print(c1())--1
    11 print(c1())--2
    12 print(c1())--3
    13 
    14 c2 = closure()--每次调用会产生闭包的方法, 都类似类一样会生成一个新的闭包函数, i 会重新计数
    15 print(c2())--1
    16 print(c2())--2
    17 
    18 print(c1())--4
    19 
    20 c1 = nil--闭包保留的变量 i 会被真正销毁

    更多Lua闭包的内容可以参考下面这篇博文:http://cn.cocos2d-x.org/tutorial/show?id=1078

  • 相关阅读:
    关于VBA的Exit For到底是怎样跳出for循环的小例子
    关于VBA的Exit For到底是怎样跳出for循环的小例子
    C#-Task.Run 和 Task.Factory.StartNew 区别
    java数组使用 四 反转数组元素
    java数组使用 三 循环数组元素
    java数组使用 二 数组的三种初始化
    java数组使用 一
    java方法 使用 四 可变参数
    java方法 使用 三 求阶乘
    java方法 使用 二 查找最大值
  • 原文地址:https://www.cnblogs.com/hammerc/p/4707125.html
Copyright © 2020-2023  润新知