您的位置:首页 > 编程语言 > Lua

Lua学习笔记 第六章 深入函数

2014-08-22 15:35 525 查看
在Lua中,函数是一种第一类值,它们具有特定的词法域;
第一类值表示函数与其他传统类型的值具有相同的权利,函数可以存储到变量中或table中,
可以作为实参传递给其他函数,还可以作为其他函数的返回值;
词法域是指一个函数可以嵌套在另一个函数中,内部的函数可以访问外部函数中的变量;
在Lua中函数与所有其它值一样都是匿名的,即它们都没有名称。当讨论一个函数名时实际
上是讨论一个持有某函数的变量;
Lua中最常见的函数编写方式,如:function foo(x) return2*x end
只是所谓的"语法糖"而已。也就是以下代码的一种简化书写形式:
foo = function (x) return 2*x end
因此一个函数定义实际上就是一条赋值语句,这条语句创建了一种类型为"函数"的值,并将这
个值赋予一个变量;
table库提供的一个函数table.sort,
它接受一个table并对其中的元素排序。
table.sort(network, function(a, b)

return(a.name > b.name)

end)
其中第二个参数就是匿名参数;
像sort这样的函数,接受另一个函数作为实参的,称其是一个"高阶函数",高阶函数是一种强大的编程机制;
 
6.1闭合函数(closure)
若把一个函数写在另一个函数之内,那么这个位于内部的函数便可以访问到外部函数中的局部变量。
这项特征称之为"词法域"!对于内部函数而言,外部函数的局部变量称为"非局部的变量";
而一个closure就是一个函数加上该函数所需访问的所有"非局部的变量";因此函数本身可以认为是一种特殊的closure;
闭合函数的例子:
do
    local oldOpen =io.open
    localaccess_OK = function(filename, mode)
            <检查访问权限>
        end
    io.open =function(filename, mode)
        if access_OK(filename,mode) then
            returnoldOpen(filename, mode)
        else
            returnnil, "access denied"
end
    end
end
 
6.2非全局的函数(non-global function)
由于函数是第一类值,因此函数不仅可以存储在全局变量中,还可以存储到table的
字段中和局部变量中;在table存储函数的几种写法:
Lib = {}

Lib.foo = function (x, y) return x + y end
Lib.g
4000
oo = 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
 
若将一个函数存储到局部变量中,即得到了一个局部函数,该函数只能在某个特定的作用域中使用;
Lua是将每个程序块(chunk)作为一个函数来处理的,所以在一个程序块中声明的函数也是局部函数;
Lua中局部函数的定义的基本语法:
local f = function (<参数>)
    <函数体>
end
对于这种局部函数的定义,Lua还支持一种特殊的"语法糖":
local function f (<参数>)
    <函数体>
end
当Lua展开定义局部函数的"语法糖"时,并不是使用定义函数的基本语法;如对于局部函数的定义:
local function foo (<参数>) <函数体> end
Lua将其展开为:
local foo
foo = function (<参数>) <函数体> end
所以在Lua中定义局部的递归函数有两种写法:
local fact

fact = function(n)
    if n== 0 thenreturn 1
    else returnn*fact(n-1)
    end
end
local function fact(n)
    if n==0 thenreturn 1
    else returnn*fact(n-1)
    end
end         --
经Lua展开后与第一种写法一样
 
6.3正确的尾调用
Lua支持尾调用消除(tail-call-elimination);
所谓"尾调用(tail call)"就是一种类似于goto的函数调用.当一个函数调用是另一个函数的最后一个动作时,
该调用才算是一条尾调用。如:
function f(x) return g(x) end
也就是说f调用完g之后就再无其它的事情可做了;因此程序就不需要返回那个尾调用所在的函数。
在尾调用之后,程序也不需要保存任何关于该函数的栈信息。当g返回时,执行的控制权可以直接
返回到调用f的那个点上。
在进行尾调用时不会消耗任何栈空间,这种实现成为支持"尾调用消除"。
由于尾调用不会耗费栈空间,所以一个程序可以拥有无数嵌套的"尾调用".如:
function foo(n)
    if n > 0then return foo(n-1) end
end
一条尾调用就好比是一条goto语句.因此Lua中尾调用的一大应用就是编写"状态机"。
这种程序通常以一个函数表示一个状态,改变状态就是goto(调用)到另一个特定的函数.
例子见P53(迷宫游戏)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  lua 脚本