<Lua程序设计(第二版)>书摘-5

资料摘自<Lua程序设计(第二版)>

深入函数
在Lua中,函数是一种"第一类值",这表示Lua中的函数与其他传统类型的值(例如数字和字符串)具有相同的权利。函数可以存储到变量或table中,可以作为实参传递给其他函数,还可以作为其他函数的返回值。
当谈论一个函数名称时(例如print)实际上是在讨论一个持有某函数的变量。
function foo(x) return 2*x end
其实是以下代码的一种简化书写形式:
foo = function (x) return 2*x end
因此一个函数定义实际就是一条赋值语句,这条语句创建了一种类型为"function"的值,并将这个值赋予一个变量。


创建一个安全的运行环境,即所谓的"沙盒"。当执行一些未受信任的代码时就需要一个安全的运行环境,例如在服务器中执行那些从internet上接收到的代码。举例来说,如果要限制一个程序访问文件的话,只需使用closure来重定义函数io.open就可以了。
do
    local oldOpen = io.open
    local access_OK = function(filename,mode)
    <检查访问权限>
    end
    io.open = function(filename,mode)
        if access_OK(filename,mode)
            return oldOpen(filename,mode)
        else
            return nil,"access denied"
        end
    end
end
这个示例的精彩之处在于,经过重新定义后,一个程序就只能通过新的受限版本来调用原来那个未受限的open函数了。示例将原来不安全的版本保存到closure的一个私有变量中,从而使得外部再无法直接访问到原来的版本了。


由于函数是一种"第一类值",因此一个显而易见的推论就是,函数不仅可以存储在全局变量中,还可以存储在table字段中和局部变量中。
前面讲到了几个将函数存储在table字段中的示例,大部分Lua库也采用了这种机制。若要在Lua中创建这种函数,只需将常规的函数语法与table语法结合起来使用即可:
Lib={}
Lib.foo = function(x,y) return x+y end
Lib.goo = function(x,y) return x-y end
在定义递归的局部函数时,还有一个特别之处需要注意。
local fact = function (n)
    if n == 0 then 
        return 1
    else 
        return n*fact(n-1)  --错误
    end
end
当Lua编译到函数体中调用fact(n-1)的地方时,由于局部的fact尚未定义完毕,因此这句表达式其实是调用了一个全局的fact,而非此函数自身。可这样解决这个问题:
local fact
fact = function (n)
    if n == 0 then 
        return 1
    else 
        return n*fact(n-1)  --错误
    end
end
现在函数中的fact调用就表示了局部变量。即使在函数定义时这个变量的值尚未完成定义,但之后在函数执行时fact则肯定已经拥有了正确的值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值