• 函数定义以function关键字开始,后面是函数名称,然后是传递给函数的参数列表。以end关键字结尾

    传入参数

    单一参数

  • 函数中的参数是局部变量,在调用结束时回收

    1. function SetName(myString)
    2. print(mtString)
    3. end

    多个参数

  • 多个参数之间使用 逗号 隔开

    function SetName(myName,myAge)
    print(myName)
    print(myAge)
    end
    

    可变长参数

  • 使用 代替参数列表

    • 在函数中使用{…}获得这个参数列表
    • Lua会创建一个局部的名字为arg的table保存所有调用时传递的参数
    • 参数个数使用arg=table.pack(…);arg.n获取
    • 开发过程中加入注释,以防忘记函数需要多少个参数
    • 结合一些必要的参数,但是必须在可边长参数之前。如:myFunction(val1,val2,…)
  • :可变长表达式,可以认为是一个多返回值的函数
    • print(…):打印…中的所有参数 ```lua function HowMany(…)
      arg=table.pack(…)
      for index = 1, arg.n do
         print(arg[index])
      
      end else print(“no value”) end end

function HowMany(val1,,val2,…)
if (arg.n > 0) then for index = 1, arg.n do print(arg[index]) end else print(val1+val2) end end

<a name="FDHop"></a>
#### select():遍历可边长参数

- **select(selector,...)**:返回**selector位置后**的所有**参数**
   - selector:开始遍历的位置,使用**"#"**则代表**输出参数个数**
```lua
print(select("#",1,2,3,4,6))    --输出:5
print(select("2",1,2,3,4,6))    --输出:2    3    4    6
print(select("3",1,2,3,4,6))    --输出:3    4    6

返回值

  • 将处理的结果返回到被调用的脚本。函数使用 return 变量 来返回
  • 可返回多个结果
    • 函数被直接用于加法运算时,只返回第一个
    • 在表达式中,多返回值函数必须是最后一个,否则也
    • 使用(function())那么永远只得到第一个返回值 ```lua function back() return 1, 2 end

x, y, z = 0, back() —多返回函数时最后一个,返回多个返回值 print(x, y, z) —输出:0 1 2 a, b, c = back(), 0 —多返回函数不是最后一个,则只返回第一个返回值 print(a, b, c) —输出:1 0

print(back(), 0) —输出:1 0 print(0, back()) —输出:0 1 2


- 还可以return返回值
   - 因为Lua在return时,就会让函数出栈,所以不会发生栈溢出的情况

<a name="M12oU"></a>
# 尾调用

- Lua中有尾调用消除的特性。
- 尾调用:当**函数1最后**一个动作是**调用函数2**而**不进行其他工作**,就会形成尾调用。
   - 尾调用后,**程序不需要再次调用栈中储存的信息**,这样尾调用就**不会使用**任何**额外的栈空间**,就**不会发生堆栈溢出**
- 注:正确的尾调用,应该在**函数**最后**调用别的函数时**,**只需调用操作**,让**调用之后不要再回**到该**原函数中运行**。
```lua
function g(n)
    if (n > 0) then
        return g(n - 1)
    end
end
--[[
该函数不会发生栈溢出,是正确的尾调用,,因为在运行return g(x-1)时,
不需要保存运行g(n)的数据到栈中,这时,栈就可以释放之前的空间,
因此就选运行无数次,都不会让栈发生溢出
--]]

function f(n)
    if (n > 0) then
        return f(n - 1)+1
    end
end
--[[
该函数会发生栈溢出,不是正确的尾调用,因为在运行return f(n-1)+1时,
在内存中,因为f(n-1)函数运行完之后,还需要回到f(n)函数中进行+1操作,
因此,此时的f(n)不能再栈中被释放,
因此在多重嵌套的情况下,可能发生栈内存溢出的情况
--]]

函数是第一类值

  • 第一类值:Lua语言中,函数其他类型的值(字符串,数字)的权限相同,可以将某个函数保存到变量

    • 如:a = print; a(“hello”);
      • 该语法令a指向print函数,之后使用a就相当于使用了print

        函数声明的完整语法

  • function foo(x) return 2*x end 相当于 foo=function(x) return 2*x end

    • 所以使用函数,相当于创建了一个类型为”function”的变量

      高阶函数

  • 在函数中可以嵌套函数(及使用高阶函数)

    • 如:table.sort()函数,可以选择使用第二个为function的参数 ```lua sort = function(a, b) return a.name > b.name end

t = { {name = “abc”}, {name = “gfs”}, {name = “zxc”}, {name = “tacx”} } table.sort(t, sort) —table.sort()函数中,可以嵌套一个类型为function的变量来设定排序方式


function calculate(f, delta) delta = delta or 1e-4 return function(x) return (f(x + delta) - f(x)) / delta end — body end c=calculate(math.sin)
—[[ c代表储存着calculate函数的变量,并且设定其函数为math.sin后 c代表 function(x) return (math.sin(x+delta)-math(x))/delta end 该高阶函数的意义是,调用时设定函数f,求该函数的导数 —]] print(c(5.2)) —相当于求math.sin(5.2)的导数


<a name="V3Lw6"></a>
# 局部函数

- 储存在局部变量中的函数
- **注:局部函数速度同样更快,但是表中的局部函数速度慢与全局函数**
<a name="jzza6"></a>
### 储存在表字段中

- 声明方式如下
```lua
--使用函数声明
Lib = {}
Lib.add = function(x, y)
    return x + y
end
Lib.sub = function(x, y)
    return x - y
end

print(Lib.add(3, 2), Lib.sub(3, 2))    --输出:5    1

--使用表构造器
Lib = {
    add = function(x, y)
        return x + y
    end,
    sub = function(x, y)
        return x - y
    end
}

--[[
在表构造器内,不能是愚弄function functionName() end的方式来构造局部函数
Lib={
    function add(x,y)
        return x+y
    end
}
--]]

--特殊构造语法
Lib = {}
function Lib.add(x, y)
    return x + y
end
function Lib.sub(x, y)
    return x - y
end

局部函数声明

  • local function f(params)

body
end
相当于
local f;
f=function(params)
body
end

  • 声明时候不使用“向前”声明可能出现错误 ```lua

local fact=function (n) if n==0 then return 1 else return nfact(n-1) end end —该代码会出现错误,因为在调用return nfact(n-1)时,fact还没被声明为局部变量, —所以会找不到该变量,修改为 local fact fact = function(n) if n == 0 then return 1 else return n * fact(n - 1) end end ```