欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《lua程序设计》读书笔记 第8章:编译、执行与错误

程序员文章站 2024-03-17 23:14:46
...

尽管Lua是一种解释型语言,但是Lua确实允许在运行源代码前,先将源代码预编译为一种中间形式。其实,区分解释型语言的主要功能并不在鱼是否能编译它们,而是在于编译器是否是语言运行时库的一部分,即是否有能力(并且轻易的)执行动态生成的代码。可以说,正是因为存在诸如dofile装的函数,才可以将Lua称为一种解释型语言。

8.1 编译

8.1.1 loadfile

Lua中dofile函数用于运行Lua代码块,但实际上dofile只是一个辅助函数,loadfile才做了真正核心的工作。loadfile从一个文件中加载Lua代码块,但是它不会运行代码,而是编译代码,将编译结果作为一个函数返回。此外,loadfile不会引发错误,它只是返回错误值而不处理错误。
一般dofile如下定义:

function dofile(filename)
    local f = assert(loadfile(filename))
    return f()
end

如果loadfile失败,那么assert将引发一个错误。

8.1.2 loadstring

函数loadstring 与loadfile类似,不同之处在于它是从一个字符串中读取代码,而不是从文件中。
loadstring 是一个开销较大的函数,应该谨慎使用。如果代码中有错误,loadstring将返回nil。loadstring在每次调用时都将编译一次代码。loadsting在编译时不涉及词法域:

i=32
local i = 0
f = loadstring("i=i+1; print(i)")
g = function() i=i+1; print(i) end
f()     -->3,使用了全局的i
g()     -->1,使用了局部的i

loadstring最典型的用法是执行外部代码,loadstring的期望输入是一个程序块,也就是一系列语句。

8.2 C代码

与Lua代码不同的是,C代码需要在使用前先链接入一个应用程序,最简单的方式是动态链接机制。Lua为几种平台实现了一套动态链接机制。Lua提供的关于动态链接的功能都聚集在一个函数中,package.loadlib,该函数有两个字符串参数:动态链接的完整路径和一个函数名。

    local path = "/user/local/lib/lua/5.1/socket.so"
    local f = package.loadlib(path, "luaopen_socket")

loadlib是一个非常底层的函数。必须提供完整的库路径以及正确的函数名称。通常使用require来加载C程序库,这个函数会搜索指定的库,然后用loadlib来加载库,并返回初始化函数。

8.3 错误

Lua可以通过一个显式的error函数来引发一个错误,通常代码如下:

if not <condition> then error(<information>) end

与之等价的是asserth函数

assert(<condition>, <information>)      -->第二个参数是可选的

8.4 错误异常与处理

如果需要在Lua中处理错误,则必须使用函数pcall来包装需要执行的代码。使用方法是通过pcall来调用可能引发错误的函数。

if pcall(foo) then
    <常规代码>
else
    <处理错误>
end

pcall函数以一种“保护模式”来调用它的第一个参数,其可以捕获函数执行种的任何错误,这样便可以在Lua中完成所有的异常处理了。

8.5 错误信息与追溯

error消息通常是一个描述了出错内容的字符串,其会附加一些关于错误发生未知的信息。
error函数还有第二个附加参数层level,用于指定调用层级中哪个层的函数来报告当前的错误,也就是说明水谁该为错误负责。

function foo(str)
    if type(str) ~= "string" then
        error("string expected", 2)
    end
    <常规代码》
end

另外debug库提供了两个通用的错误处理函数,一个是debug.debug,它会提供一个Lua提示符,让用户来检查错误的原因;另一个是debug.traceback,它会根据调用栈来构建一个扩展的错误消息,可以在任何时候调用这个函数来获取当前执行的堆栈信息。
此两个函数可以配合xpcall函数使用,xpcall比pcall多了一个参数–一个错误处理函数。当发生错误时,Lua会调用错误处理函数。