Lua-编译,执行和错误

目录

一、Lua的"编译":把代码变成可执行的"函数"

1、dofile:简单但不灵活的"一键运行"

2、loadfile:更灵活的"编译后再执行"

3、loadstring:从"字符串"编译代码

4、三者的关系

二、编译的"坑":作用域和性能

1.作用域问题(词法域VS全局编译)

2."函数定义是赋值操作"的误解

[三、更底层的 load 函数(了解即可)](#三、更底层的 load 函数(了解即可))

四、错误处理:让程序更健壮

[1、主动触发错误:error 函数](#1、主动触发错误:error 函数)

[2、简化错误处理:assert 函数](#2、简化错误处理:assert 函数)

3、补充细节


一、Lua的"编译":把代码变成可执行的"函数"

Lua虽然是解释型语言,但它会把源代码预编译成中间形式(可以理解为"可执行的函数"),再执行。这部分核心是三个函数:dofile、loadfile、loadstring。

1、dofile:简单但不灵活的"一键运行"

作用:加载并运行一个Lua文件,相当于"打开文件->编译->执行"一步到位

实例:

Lua 复制代码
dofile("test.lua")--直接运行test.lua中的代码

缺点:如果文件加载失败,会直接报错;并且每次调用都要重新编译,效率不高。

2、loadfile:更灵活的"编译后再执行"

作用:只编译文件,不直接执行,返回一个编译后的函数。用户可以决定什么时候执行这个函数。

实例:

Lua 复制代码
local f = loadfile("test.lua") --编译该文件,返回一个函数
f();  --手动调用编译后的代码
f();  --可以多次调用,不用重复重复编译

优点:

编译一次,可以多次执行;

加载失败时会返回nil+错误信息,方遍自定义错误处理。

3、loadstring:从"字符串"编译代码

作用:和loadfile像似,但是他是从字符串中提取代码并运行,返回一个函数。

实例:

Lua 复制代码
local f = loadstring("print("hello")") --把字符串里面的代码编译
f()  --编译执行分离
4、三者的关系

dofile就是loadfile的简易包装

Lua 复制代码
function dofile(filename)
    local f = assert(loadfile(filename))
    f()
end

二、编译的"坑":作用域和性能

1.作用域问题(词法域VS全局编译)

loadfile编译代码时,不考虑"词法作用域"(即外层函数的局部变量),它编译的代码默认在全局环境中执行。

Lua 复制代码
local i = 0
local f = loadstring("i = i + 1; print(i)")  -- 这里的 i 是全局的 i
local g = function() i = i + 1; print(i) end  -- 这里的 i 是外层的局部 i

f()  --> 1 (修改了全局 i)
g()  --> 2 (修改了外层的局部 i)
2."函数定义是赋值操作"的误解

Lua中加载代码块(如loadfile加载包含函数定义的文件)时,函数定义的本质是"赋值操作",需要手动执行编译后才能完成定义。

Lua 复制代码
--foo.lua文件内容
function foo(x)
    print(x)
end

--main.lua的内容
f = loadfile("foo.lua")
print(foo) -> nil 还未定义
f()
print(foo) -> function的地址,完成了定义
print(foo(999))-> 999 函数可以正常调用

三、更底层的 load 函数(了解即可)

loadfileloadstring 都是基于 load 实现的。load 更灵活,它可以从 "自定义的读取器" 中获取代码(比如分块读取大文件),但平时用得少,知道即可。

四、错误处理:让程序更健壮

1、主动触发错误:error 函数

error 函数的作用是显式地在代码中抛出错误,中断程序执行并提示错误信息。

  • 语法:error(错误消息 [, 错误级别])

  • 示例(用户输入校验): lua

    复制代码
    print("enter a number:")
    n = io.read("*number")  -- 读取数字,若输入非数字则返回 nil
    if not n then
      error("invalid input")  -- 输入无效时,主动抛出错误
    end

    执行后,若输入非数字,程序会中断并提示 invalid input

2、简化错误处理:assert 函数

assert 是 Lua 内置的 "断言函数",用于简化 "条件不满足则抛错" 的逻辑 ,相当于 if not 条件 then error(消息) end 的简写。

  • 语法:assert(条件, 错误消息)

    • 条件true,返回 条件 的值;
    • 条件falsenil,则抛出 错误消息
  • 示例(简化上面的输入校验): lua

    复制代码
    print("enter a number:")
    n = assert(io.read("*number"), "invalid input")

    效果和用 error 手动判断完全一致,但代码更简洁。

3、补充细节
  • 错误级别的控制error 可选第二个参数控制 "错误在调用栈中的层级",一般用默认值(2)即可,不用额外关注。

  • 与元表的关联 :文末注释提到 "这些操作可通过元表合法化",比如对非 table 进行索引时,若元表定义了 __index,则不会直接报错(后续元表章节会详细讲)。

    -- 捕获 loadstring 的错误
    local f = assert(loadstring("i = i +", "语法错误的代码"))
    -- 如果 loadstring 失败,assert 会抛出清晰的错误

相关推荐
前端世界4 小时前
当网络里混入“假网关”:用 Scapy 写一个 DHCP 欺骗检测器(附完整代码与讲解)
开发语言·网络·php
l1t4 小时前
Duckdb rusty_sheet插件使用心得
数据库·sql·lua·duckdb·rusty_sheet
赵谨言4 小时前
基于python二手车价值评估系统的设计与实现
大数据·开发语言·经验分享·python
java1234_小锋4 小时前
PyTorch2 Python深度学习 - 初识PyTorch2,实现一个简单的线性神经网络
开发语言·python·深度学习·pytorch2
胡萝卜3.04 小时前
C++面向对象继承全面解析:不能被继承的类、多继承、菱形虚拟继承与设计模式实践
开发语言·c++·人工智能·stl·继承·菱形继承·组合vs继承
Violet_YSWY5 小时前
将axios、async、Promise联系在一起讲一下&讲一下.then 与其关系
开发语言·前端·javascript
luoganttcc5 小时前
用Python的trimesh库计算3DTiles体积的具体代码示例
开发语言·python·3d
我爱画页面5 小时前
vue3封装table组件及属性介绍
开发语言·javascript·ecmascript
逻极5 小时前
Next.js vs Vue.js:2025年全栈战场,谁主沉浮?
开发语言·javascript·vue.js·reactjs