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

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.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

 

若将一个函数存储到局部变量中,即得到了一个局部函数,该函数只能在某个特定的作用域中使用;

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(迷宫游戏)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值