Programming in Lua(Thrid Edition)笔记---6 More about Functions

6 Mor about Functions

  • Lua的函数没有名字,其所谓的名字只是一个标签

    1
    2
    3
    4
    5
    6
    a = {p = print}
    a.p("Hello world!") --> Hello world
    print = math.sin -- 'print' now refers to the sine function
    a.p(print(1)) --> 0.841470
    sin = a.p -- 'sin' now refers to the print function
    sin(10, 20) --> 10 20
  • 函数构造语法糖:

    1
    function foo(x) return 2 * x end

可写作

1
foo = function (x) return 2 * x end

anonymous function

  • table.sort()的参数可以为无名函数
    1
    2
    3
    4
    5
    6
    7
    network = {
    {name="grauna", IP="210.26.30.34"},
    {name="arraial", IP="210.26.30.23"},
    {name="lua", IP="210.26.23.12"},
    {name="derain", IP="210.26.23.20"},
    }
    table.sort(network, function (a, b) return (a.name > b.name) end)

可用函数做参数的函数叫做higher-order function

  • 导函数
    1
    2
    3
    4
    5
    6
    7
    function derivative(f, delta)
    delta = delta or 1e-4
    return
    function (x)
    return (f(x + delta) - f(x)) / delta
    end
    end

返回值也是一个函数

  • Lua的函数可存储在table中,构造方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Lib = {}
    Lib.foo = function (x, y) return x + y end
    Lib.goo = function (x, y) return x - y end
    Lib = {
    foo = function (x, y) return x + y end,
    goo = function (x, y) return x - y end
    }
    Lib = {}
    function Lib.foo(x, y) return x + y end
    function Lib.goo(x, y) return x - y end
  • 递归局部函数

    1
    2
    3
    4
    local fact = function (n)
    if n == 0 then return 1
    else return n * fact(n - 1) -- buggy
    end

在编译fact(n - 1)时,局部函数fact()尚未定义,其会去调用全局的函数,解决方法:先定义变量,再定义函数

1
2
3
4
5
6
local fact
fact = function (n)
if n == 0 then return 1
else return n * fact(n - 1)
end
end

  • Lua会将局部函数语法糖拓展为递归安全形式
    1
    local function foo(<params>) <body> end

拓展为

1
local foo; foo = function (<params>) <body> end

这一拓展对间接递归函数无效,这时需要手动修改

1
2
3
4
5
6
7
local f, g -- 'forward' declarations
function g()
<some code> f() <some code>
end
function f()
<some code> g() <some coe>
end

这里要注意function f()不能写为local function f(),否则Lua会拓展出新的f的定义而使之前的f()未定义

  • Lua利用goto实现尾调函数消除,从而无需额外的栈空间,所以嵌套尾调函数的调用次数无限制,不会出现栈溢出
    1
    function f(x) return g(x) end

以下函数或语句无法消除

1
2
3
4
function f(x) g(x) end -- after calling g, f has to discard occasional results from g before returning
return g(x) + 1 -- must do the addition
return x or g(x) -- must adjust to 1 result
return (g(x)) -- must adjust to 1 result

由于Lua先求值再调用,所用尾调函数的表达式和参数表达式可以很复杂

1
return x[i].foo(x[j] + a * b, i + j)