lua基础02

来源:互联网 发布:淘宝快递单打印机设置 编辑:程序博客网 时间:2024/06/06 03:39

1、迭代器与闭包

利用闭包可以访问外部局部变量的特性来实现迭代器:

function list_iter(t)

local i = 0

local n = table.maxn(t)

return function ()

i = i + 1

if i <= n then return t[i] end

end

end

2、泛型for的语义

for <var-list> in <exp-list> do

<body>

end

var-list中的第一个变量为控制变量,其值为nil时循环结束。exp-list应该返回泛型for需要的三个参数(迭代函数、状态常量、控制变量),然后将状态常量和控制变量作为参数调用迭代函数。然后将迭代函数返回的值赋给var-list,如果第一个变量为nil则结束循环。

3、无状态的迭代器

for i,v in ipairs(t) do print(i) end

调用ipairs函数时,返回迭代函数,状态常量t,控制变量i,然后用着两个变量继续调用迭代函数

NOTE:我们应该尽量写无状态的迭代器,如果无法实现功能则尽量使用闭包的迭代器。

4、编译和运行

解释型语言的特征不在于他们是否被编译,而是编译器是语言运行时的一部分。

dofile()函数:每次都需要编译并且自动运行,出错时中断

loadfile()函数:只需要编译一次,可多次运行,出错时返回nil和错误信息,便于定位。

dostring()和loadstring()与 *file类似,只是字符串中的变量都是全局变量。

!!!!Lua中的函数定义是发生在运行时的赋值而不是编译时。

require()函数:与dofile()完成的功能相同,不过有两点不同;

1)require会搜索目录加载文件。先检查全局变量LUA_PATH是否为字符串,如果是则这就是路径,否则检查环境变量LUA_PATH的值,如果都失败则使用固定默认值。

2)require会自动判断以避免重复加载同一个文件。LUA将已经加载的文件都放在一个table中,加载前先检查是否存在,若存在直接返回。可以通过_LOADED全局变量来访问文件列表。特别的,如果是require(foo) require(foo.lua)将会加载文件两次,这是因为table中的虚文件名不同。

LUA打破平台兼容的原则为各个平台实现了动态链接的机制。这是个特例,一旦拥有了动态链接机制,就可以动态的加载各种LUA中不存在的机制。

loadlib()函数提供了所有的动态链接的功能,有两个参数,库的绝对路径和初始化函数

local path = "usr/local/lua/lib/libluasocket.so"

local foo = loadlib(path,"luaopen_socket")

此函数加载指定的库并链接到Lua,然而并没有调用库的初始化函数,只是返回了初始化函数作为Lua的一个函数,我们可以直接在Lua中调用库的初始化,若加载或者初始化失败则返回nil和错误信息。

5、错误

Lua经常作为扩展语言嵌入到别的应用中,所以不能简单的发生错误时就崩溃,应当在Lua发生错误时结束当前chunck并返回到应用中。

当函数遇到异常有两个基本的操作:返回错误代码或者抛出异常。通常,对于能够避免的逻辑错误,以抛出错误的方式处理,否则返回错误的代码。

6、异常

如果在Lua中需要处理错误,需要使用pcall函数来封装你的代码。

function foo()

...

end

if pcall(foo) then

-- no errors

else

-- has errors

end

若foo正常,pcall返回true和foo()的执行结果,否则返回nil和错误信息。

xpcall()函数可以保存错误发生时的栈信息,接受两个参数,调用函数和错误处理函数。当错误发生时,Lua会在栈释放以前调用错误处理函数,因此可以使用debug库收集错误信息,

print(debug.traceback())打印更多的错误信息。









0 0
原创粉丝点击