lua

2.3k 词

函数

函数定义
1
2
3
function function_name (arc)  -- arc 表示参数列表,函数的参数列表可以为空
   -- body
end
1
2
3
local function function_name (arc)
  -- body
end

由于全局变量一般会污染全局名字空间,同时也有性能损耗(即查询全局环境表的开销),因此我们应当尽量使用“局部函数”,其记法是类似的,只是开头加上 local 修饰符

函数的参数
  1. 按值传递(在调用函数的时候,若形参个数和实参个数不同时,Lua 会自动调整实参个数。调整规则:若实参个数大于形参个数,从左向右,多余的实参被忽略;若实参个数小于形参个数,从左向右,没有被实参初始化的形参会被初始化为 nil。
  2. 按引用传递(在常用基本类型中,除了 table 是按址传递类型外,其它的都是按值传递参数)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    local function func( ... )                -- 形参为 ... ,表示函数采用变长参数
    

    local temp = {…} – 访问的时候也要使用 …
    local ans = table.concat(temp, " ") – 使用 table.concat 库函数对数
    – 组内容使用 " " 拼接成字符串。
    print(ans)
    end

    func(1, 2) – 传递了两个参数
    func(1, 2, 3, 4) – 传递了四个参数

变长参数 LuaJIT 2 尚不能 JIT 编译这种变长参数的用法,只能解释执行。所以对性能敏感的代码,应当避免使用此种形式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
local function change(arg) -- change 函数,改变长方形的长和宽,使其各增长一倍
  arg.width = arg.width * 2
  arg.height = arg.height * 2
  return arg
end

local rectangle = { width = 20, height = 15 }
print(“before change:”, “width =”, rectangle.width,
“height =”, rectangle.height)
rectangle = change(rectangle)
print(“after change:”, “width =”, rectangle.width,
“height =”, rectangle.height)

具名参数(所有的实参组织到一个 table 中,并将这个 table 作为唯一的实参传给函数)

函数返回值
  1. 允许多个返回值
  2. 当函数返回值的个数和接收返回值的变量的个数不一致时,Lua 也会自动调整参数个数( 调整规则: 若返回值个数大于接收变量的个数,多余的返回值会被忽略掉; 若返回值个数小于参数个数,从左向右,没有被返回值初始化的变量会被初始化为 nil。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    local function init()       -- init 函数 返回两个值 1 和 "lua"
    return 1, "lua"
    end
    

    local x, y, z = init(), 2 – init 函数的位置不在最后,此时只返回 1
    print(x, y, z) –>output 1 2 nil

    local a, b, c = 2, init() – init 函数的位置在最后,此时返回 1 和 “lua”
    print(a, b, c) –>output 2 1 lua

当一个函数有一个以上返回值,且函数调用不是一个列表表达式的最后一个元素,那么函数调用只会产生一个返回值, 也就是第一个返回值。

如果实参列表中某个函数会返回多个值,同时调用者又没有显式地使用括号运算符来筛选和过滤,则这样的表达式是不能被 LuaJIT 2 所 JIT 编译的,而只能被解释执行。

全动态函数调用
  1. 使用场景

    • 你要调用的函数参数是未知的;
    • 函数的实际参数的类型和数目也都是未知的

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      
      local function run(x, y)
      print('run', x, y)
      end
      

      local function attack(targetId)
      print(‘targetId’, targetId)
      end

      local function do_action(method, …)
      local args = {…} or {}
      method(unpack(args, 1, table.maxn(args)))
      end

      do_action(run, 1, 2) – output: run 1 2
      do_action(attack, 1111) – output: targetId 1111

unpack 内建函数还不能为 LuaJIT 所 JIT 编译,因此这种用法总是会被解释执行。对性能敏感的代码路径应避免这种用法。

模块


用法

my.lua

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
local foo={}

local function getname()
return “Lucy”
end

function foo.greeting()
print("hello " … getname())
end

return foo

main.lua

1
2
local fp = require("my")
fp.greeting()     -->output: hello Lucy

string库

了解哈即可

table 库

了解即可
注意数组获取长度
  1. 对于常规的数组,里面从 1 到 n 放着一些非空的值的时候,它的长度就精确的为 n,即最后一个值的下标。如果数组有一个“空洞”(就是说,nil 值被夹在非空值之间),那么 #t 可能是指向任何一个是 nil 值的前一个位置的下标(就是说,任何一个 nil 值都有可能被当成数组的结束)。这也就说明对于有“空洞”的情况,table 的长度存在一定的 不可确定性。

时间库尽量用ngx_lua模块提供的