跟着 Lua 5.1 官方参考文档学习 Lua (2)
文章目录
- 2.3 – Variables
- 2.4 – Statements
- 2.4.1 – Chunks
- 2.4.2 – Blocks
- 2.4.3 – Assignment
- 2.4.4 – Control Structures
- 2.4.5 – For Statement
- 2.4.6 – Function Calls as Statements
- 2.4.7 – Local Declarations
2.3 – Variables
Variables are places that store values. There are three kinds of variables in Lua: global variables, local variables, and table fields.
A single name can denote a global variable or a local variable (or a function’s formal parameter, which is a particular kind of local variable):
var ::= Name
Name denotes identifiers, as defined in §2.1.
Any variable is assumed to be global unless explicitly declared as a local (see §2.4.7). Local variables are lexically scoped: local variables can be freely accessed by functions defined inside their scope (see §2.6).
Before the first assignment to a variable, its value is nil.
Square brackets are used to index a table:
var ::= prefixexp `[´ exp `]´
The meaning of accesses to global variables and table fields can be changed via metatables. An access to an indexed variable t[i] is equivalent to a call gettable_event(t,i). (See §2.8 for a complete description of the gettable_event function. This function is not defined or callable in Lua. We use it here only for explanatory purposes.)
The syntax var.Name is just syntactic sugar for var["Name"]:
var ::= prefixexp `.´ Name
All global variables live as fields in ordinary Lua tables, called environment tables or simply environments (see §2.9). Each function has its own reference to an environment, so that all global variables in this function will refer to this environment table. When a function is created, it inherits the environment from the function that created it. To get the environment table of a Lua function, you call getfenv. To replace it, you call setfenv. (You can only manipulate the environment of C functions through the debug library; (see §5.9).)
例子:修改 Lua 函数的环境
x = 10function foo()print("x= ", x)
endfoo()-- 修改Lua函数的环境
local new_env = {x = 20, print = print}
setfenv(foo, new_env)foo()
输出
x= 10
x= 20
An access to a global variable x is equivalent to _env.x, which in turn is equivalent to
gettable_event(_env, "x")
where _env is the environment of the running function. (See §2.8 for a complete description of the gettable_event function. This function is not defined or callable in Lua. Similarly, the _env variable is not defined in Lua. We use them here only for explanatory purposes.)
gettable_event 函数
function gettable_event (table, key)local hif type(table) == "table" thenlocal v = rawget(table, key)if v ~= nil then return v endh = metatable(table).__indexif h == nil then return nil endelseh = metatable(table).__indexif h == nil thenerror(···)endendif type(h) == "function" thenreturn (h(table, key)) -- call the handlerelse return h[key] -- or repeat operation on itendend
2.4 – Statements
Lua supports an almost conventional set of statements, similar to those in Pascal or C. This set includes assignments, control structures, function calls, and variable declarations.
2.4.1 – Chunks
The unit of execution of Lua is called a chunk. A chunk is simply a sequence of statements, which are executed sequentially. Each statement can be optionally followed by a semicolon:
chunk ::= {stat [`;´]}
There are no empty statements and thus ‘;;’ is not legal.
例子:4 个等价的 chunk
a = 1
b = a*2a = 1;
b = a*2;a = 1; b = a*2a = 1 b = a*2 -- ugly, but valid
Lua handles a chunk as the body of an anonymous function with a variable number of arguments (see §2.5.9). As such, chunks can define local variables, receive arguments, and return values.
A chunk can be stored in a file or in a string inside the host program. To execute a chunk, Lua first pre-compiles the chunk into instructions for a virtual machine, and then it executes the compiled code with an interpreter for the virtual machine.
例子:使用 C API 给 Lua chunk 传递参数,获取返回值
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>int main() {lua_State *L = luaL_newstate(); // 创建一个新的 Lua 状态luaL_openlibs(L); // 打开 Lua 标准库// chunk 代码const char *chunk = "local s = 0\n""for i, v in ipairs{...} do\n"" s = s + v\n""end\n""return s\n";// 加载 chunkif (luaL_loadstring(L, chunk) != 0) {printf("load error!\n");return 1;}// 给 chunk 传递参数lua_pushnumber(L, 1);lua_pushnumber(L, 2);lua_pushnumber(L, 3);// 执行 chunk。3个参数,1个返回值lua_call(L, 3, 1);// 检查返回值if (lua_isnumber(L, -1)) {double x = lua_tonumber(L, -1);printf("result= %f\n", x); // 输出结果}lua_pop(L, 1); // 弹出返回值lua_close(L); // 关闭 Lua 状态return 0;
}
例子:Lua 中给 chunk 传递参数,获取返回值
-- chunk 代码
local chunk = [[
local s = 0
for i, v in ipairs{...} do
s = s + v
end
return s
]]-- 加载 chunk
local f, err = loadstring(chunk)
if err thenerror(err)
end-- 执行 chunk。3个参数,1个返回值
local success, res = pcall(f, 1, 2, 3)
if not success thenprint("pcall error: ", res)
elseprint("res= ", res)
end
补充:
Lua treats any independent chunk as the body of an anonymous function with a variable number of arguments. For instance, loadstring(“a = 1”) returns the equivalent of the following expression:
function (...) a = 1 end
Like any other function, chunks can declare local variables:
f = loadstring("local a = 10; print(a + 20)")
f() --> 30
Chunks can also be pre-compiled into binary form; see program luac for details. Programs in source and compiled forms are interchangeable; Lua automatically detects the file type and acts accordingly.
2.4.2 – Blocks
A block is a list of statements; syntactically, a block is the same as a chunk:
block ::= chunk
A block can be explicitly delimited to produce a single statement:
stat ::= do block end
Explicit blocks are useful to control the scope of variable declarations. Explicit blocks are also sometimes used to add a return or break statement in the middle of another block (see §2.4.4).
2.4.3 – Assignment
Lua allows multiple assignments. Therefore, the syntax for assignment defines a list of variables on the left side and a list of expressions on the right side. The elements in both lists are separated by commas:
stat ::= varlist `=´ explistvarlist ::= var {`,´ var}explist ::= exp {`,´ exp}
Expressions are discussed in §2.5.
Before the assignment, the list of values is adjusted to the length of the list of variables. If there are more values than needed, the excess values are thrown away. If there are fewer values than needed, the list is extended with as many nil’s as needed.
例子:赋值语句
local a, b = 1, 2, 3
print(a, b)local c, d, e = 1, 2
print(c, d, e)
输出
1 2
1 2 nil
If the list of expressions ends with a function call, then all values returned by that call enter the list of values, before the adjustment (except when the call is enclosed in parentheses; see §2.5).
例子:最后一个表达式是函数调用
function foo()return 1, 2, 3
endlocal a, b, c = 1, foo()
print(a, b, c)local d, e, f = 1, 2, (foo())
print(d, e, f)
输出
1 1 2
1 2 1
The assignment statement first evaluates all its expressions and only then are the assignments performed. Thus the code
i = 3i, a[i] = i+1, 20
sets a[3] to 20, without affecting a[4] because the i in a[i] is evaluated (to 3) before it is assigned 4. Similarly, the line
x, y = y, x
exchanges the values of x and y, and
x, y, z = y, z, x
cyclically permutes the values of x, y, and z.
例子:赋值语句
a = {}
i = 3
i, a[i] = i+1, 20
print("i=", i)
print("a[3]=", a[3])
print("a[4]=", a[4])x, y, z = 1, 2, 3
x, y, z = y, z, x
print(x, y, z)
输出
i= 4
a[3]= 20
a[4]= nil
2 3 1
解释
i, a[i] = i+1, 20
因为先求值,所以a[i]中的i表达式求值为3,右边的表达式求值为4,20。赋值后i变成4,a[3]变成20。
The meaning of assignments to global variables and table fields can be changed via metatables. An assignment to an indexed variable t[i] = val is equivalent to settable_event(t,i,val). (See §2.8 for a complete description of the settable_event function. This function is not defined or callable in Lua. We use it here only for explanatory purposes.)
An assignment to a global variable x = val is equivalent to the assignment _env.x = val, which in turn is equivalent to
settable_event(_env, "x", val)
where _env is the environment of the running function. (The _env variable is not defined in Lua. We use it here only for explanatory purposes.)
settable_event 函数
function settable_event (table, key, value)local hif type(table) == "table" thenlocal v = rawget(table, key)if v ~= nil then rawset(table, key, value); return endh = metatable(table).__newindexif h == nil then rawset(table, key, value); return endelseh = metatable(table).__newindexif h == nil thenerror(···)endendif type(h) == "function" thenh(table, key,value) -- call the handlerelse h[key] = value -- or repeat operation on itendend
2.4.4 – Control Structures
The control structures if, while, and repeat have the usual meaning and familiar syntax:
stat ::= while exp do block endstat ::= repeat block until expstat ::= if exp then block {elseif exp then block} [else block] end
Lua also has a for statement, in two flavors (see §2.4.5).
The condition expression of a control structure can return any value. Both false and nil are considered false. All values different from nil and false are considered true (in particular, the number 0 and the empty string are also true).
In the repeat–until loop, the inner block does not end at the until keyword, but only after the condition. So, the condition can refer to local variables declared inside the loop block.
例子:repeat-until 循环
local x = 9
local sqr = x/2
repeatsqr = (sqr + x/sqr)/2local error = math.abs(sqr^2 - x)
until error < x/10000 -- ’error’ still visible hereprint("sqr=", sqr)
The return statement is used to return values from a function or a chunk (which is just a function). Functions and chunks can return more than one value, and so the syntax for the return statement is
stat ::= return [explist]
The break statement is used to terminate the execution of a while, repeat, or for loop, skipping to the next statement after the loop:
stat ::= break
A break ends the innermost enclosing loop.
The return and break statements can only be written as the last statement of a block. If it is really necessary to return or break in the middle of a block, then an explicit inner block can be used, as in the idioms do return end and do break end, because now return and break are the last statements in their (inner) blocks.
例子:return 语句在 block 中间
function foo()do return end -- return 语句不是末尾会报错,需要改成 do return endlocal a = 1print("a")
endfoo()
2.4.5 – For Statement
The for statement has two forms: one numeric and one generic.
The numeric for loop repeats a block of code while a control variable runs through an arithmetic progression. It has the following syntax:
stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end
The block is repeated for name starting at the value of the first exp, until it passes the second exp by steps of the third exp. More precisely, a for statement like
for v = e1, e2, e3 do block end
is equivalent to the code:
dolocal var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)if not (var and limit and step) then error() endwhile (step > 0 and var <= limit) or (step <= 0 and var >= limit) dolocal v = varblockvar = var + stependend
Note the following:
- All three control expressions are evaluated only once, before the loop starts. They must all result in numbers.
*var*,*limit*, and*step*are invisible variables. The names shown here are for explanatory purposes only.- If the third expression (the step) is absent, then a step of 1 is used.
- You can use break to exit a for loop.
- The loop variable
vis local to the loop; you cannot use its value after the for ends or is broken. If you need this value, assign it to another variable before breaking or exiting the loop.
例子:第一种形式的 for 循环
for i = 1, 10, 2 doprint(i) -- 1 3 5 7 9
endfor i = 5, 1, -1 doprint(i) -- 5 4 3 2 1
end
The generic for statement works over functions, called iterators. On each iteration, the iterator function is called to produce a new value, stopping when this new value is nil. The generic for loop has the following syntax:
stat ::= for namelist in explist do block endnamelist ::= Name {`,´ Name}
A for statement like
for var_1, ···, var_n in explist do block end
is equivalent to the code:
dolocal f, s, var = explistwhile true dolocal var_1, ···, var_n = f(s, var)var = var_1if var == nil then break endblockendend
Note the following:
*explist*is evaluated only once. Its results are an iterator function, a state, and an initial value for the first iterator variable.*f*,*s*, and*var*are invisible variables. The names are here for explanatory purposes only.- You can use break to exit a for loop.
- The loop variables
*var_i*are local to the loop; you cannot use their values after the for ends. If you need these values, then assign them to other variables before breaking or exiting the loop.
补充:Despite its apparent simplicity, the generic for is powerful. With proper iterators, we can traverse almost anything in a readable fashion. The standard libraries provide several iterators, which allow us to iterate over the lines of a file (io.lines), the pairs of a table (pairs), the entries of an array (ipairs), the words of a string (string.gmatch), and so on. Of course, we can write our own
iterators.
例子:第二种形式的 for 循环,实现 ipairs 和 pair 函数
local function iter(a, i)i = i + 1local v = a[i]if v thenreturn i, vend
endfunction ipairs(a)return iter, a, 0
endlocal a = {"a", "b", "c" ,"d"}
for i,v in ipairs(a) doprint(i, v)
endfunction pairs(t)return next, t, nil
endlocal t = {a = 1, b = 2, c = 3}
for k,v in pairs(t) doprint(k, v)
end
2.4.6 – Function Calls as Statements
To allow possible side-effects, function calls can be executed as statements:
stat ::= functioncall
In this case, all returned values are thrown away. Function calls are explained in §2.5.8.
函数调用作为一条语句,所有的返回值会被丢弃。
2.4.7 – Local Declarations
Local variables can be declared anywhere inside a block. The declaration can include an initial assignment:
stat ::= local namelist [`=´ explist]
If present, an initial assignment has the same semantics of a multiple assignment (see §2.4.3). Otherwise, all variables are initialized with nil.
A chunk is also a block (see §2.4.1), and so local variables can be declared in a chunk outside any explicit block. The scope of such local variables extends until the end of the chunk.
The visibility rules for local variables are explained in §2.6.
相关文章:
跟着 Lua 5.1 官方参考文档学习 Lua (2)
文章目录 2.3 – Variables2.4 – Statements2.4.1 – Chunks2.4.2 – Blocks2.4.3 – Assignment2.4.4 – Control Structures2.4.5 – For Statement2.4.6 – Function Calls as Statements2.4.7 – Local Declarations 2.3 – Variables Variables are places that store v…...
Python基于循环神经网络的情感分类系统(附源码,文档说明)
博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇dz…...
Zookeeper应用案例-分布式锁-实现思路
以下是具体实现代码 第一步:注册锁节点 第二步:获取锁节点,如果自己是最小的节点,就获取权限 第三步:拿到锁就开始自己的业务逻辑 第四步:业务逻辑好了就要释放这把锁 第五步:重新注册监听&…...
java练习(32)
ps:题目来自力扣 环形链表 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表…...
伯克利 CS61A 课堂笔记 10 —— Trees
本系列为加州伯克利大学著名 Python 基础课程 CS61A 的课堂笔记整理,全英文内容,文末附词汇解释。 目录 01 Trees 树 Ⅰ Tree Abstraction Ⅱ Implementing the Tree Abstraction 02 Tree Processing 建树过程 Ⅰ Fibonacci tree Ⅱ Tree Process…...
让编程变成一种享受-明基RD320U显示器
引言 作为一名有着多年JAVA开发经验的从业者,在工作过程中,显示器的重要性不言而喻。它不仅是我们与代码交互的窗口,更是影响工作效率和体验的关键因素。在多年的编程生涯中,我遇到过各种各样的问题。比如,在进行代码…...
10分钟上手DeepSeek开发:SpringBoot + Vue2快速构建AI对话系统
作者:后端小肥肠 目录 1. 前言 为什么选择DeepSeek? 本文技术栈 2. 环境准备 2.1. 后端项目初始化 2.2. 前端项目初始化 3. 后端服务开发 3.1. 配置文件 3.2. 核心服务实现 4. 前端服务开发 4.1. 聊天组件ChatWindow.vue开发 5. 效果展示及源…...
LeetCode 0624.数组列表中的最大距离:只关心最小最大值
【LetMeFly】624.数组列表中的最大距离:只关心最小最大值 力扣题目链接:https://leetcode.cn/problems/maximum-distance-in-arrays/ 给定 m 个数组,每个数组都已经按照升序排好序了。 现在你需要从两个不同的数组中选择两个整数ÿ…...
如何解决服务器端口被攻击:全面防护与快速响应
服务器端口被攻击是网络安全中常见的问题之一,尤其是当服务器暴露在公共网络上时,容易成为黑客的目标。攻击者可能通过扫描开放端口、利用漏洞或发动拒绝服务(DoS/DDoS)攻击来破坏服务器的正常运行。本文将详细介绍如何检测、防御…...
Golang深度学习
前言 在2009年,Google公司发布了一种新的编程语言,名为Go(或称为Golang),旨在提高编程效率、简化并发编程,并提供强大的标准库支持。Go语言的设计者们希望通过Go语言能够解决软件开发中的一些长期存在的问…...
Linux环境开发工具
Linux软件包管理器yum Linux下安装软件方式: 源代码安装rpm安装——Linux安装包yum安装——解决安装源、安装版本、安装依赖的问题 yum对应于Windows系统下的应用商店 使用Linux系统的人:大部分是职业程序员 客户端怎么知道去哪里下载软件࿱…...
JupyterNotebook高级使用:常用魔法命令
%%writefile test.py def Test(name):print("Test",name,"success")运行结果:就是在我们的文件目录下面创建了这个test.py文件,主要是认识一下这个里面的%%writefile表示创建新的文件,这个文件里面的内容就是上面我们定义…...
C++ Primer 类的作用域
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
【建设工程经济】2.1-2.2 经济效果评价的相关概念及指标体系
一、学前建议 学习内容主要有: ①财务评价的内容:盈利能力分析、偿债能力分析、财务可持续能力分析(财务生存能力); ②经济效果评价方法分类:确定性和不确定性评价、定量分析和定性分析、静态分析和动态分…...
如何用ollama快速布署deepseek-r1大模型
deepseek在春节期间因为特朗普的一番发言而在中国已几乎人尽皆知,热度到了连90高寿的老父亲都向我推荐这个中国产的AI大模型,而且它是开源的!我试验了下,用ollama也可以快速度安装布署deepseek-r1大模型。本想写篇文章来介绍下dee…...
50页PDF|数字化转型成熟度模型与评估(附下载)
一、前言 这份报告依据GBT 43439-2023标准,详细介绍了数字化转型的成熟度模型和评估方法。报告将成熟度分为五个等级,从一级的基础转型意识,到五级的基于数据的生态价值构建与创新,涵盖了组织、技术、数据、资源、数字化运营等多…...
机器学习实战(8):降维技术——主成分分析(PCA)
第8集:降维技术——主成分分析(PCA) 在机器学习中,降维(Dimensionality Reduction) 是一种重要的数据处理技术,用于减少特征维度、去除噪声并提高模型效率。主成分分析(Principal C…...
面试编程题
1. 请写出string类的定义,要求有构造函数,析构函数,拷贝,赋值函数。 #include <cstring> #include <algorithm>class String { public:explicit String(const char* str nullptr){if(str){str_ new char[strlen(st…...
Transformer多头注意力并行计算原理与工业级实现:从数学推导到PyTorch工程优化
一、核心数学原理剖析 1.1 多头注意力矩阵分解 Q XW^Q ∈ R^{nd_k} K XW^K ∈ R^{nd_k} V XW^V ∈ R^{nd_v} 多头分解公式: head_i Attention(QW_i^Q, KW_i^K, VW_i^V) 其中 W_i^Q ∈ R^{d_kd_k/h}, W_i^K ∈ R^{d_kd_k/h}, W_i^V ∈ R^{d_vd_v/h} (h为头数…...
我的2025年计划
新春佳节已过去了,又是一年伊始,即将步入漫长的工作、生活中了。一年之计在于春,我也不能免俗。 本文从工作生活两方面,列出一些计划。到年底,再回过头来看看,有哪些实现了,有哪些未实现。 工作…...
软件开源与AI开源的区别
一.软件开源 软件开源是指软件的源代码对公众开放,允许用户自由使用、修改和分发的软件。 核心特性:低成本(通常免费)、高可定制性(源代码可用,开发人员可以修改)、社区支持(庞大的…...
前端插件使用xlsx-populate,花样配置excel内容,根据坐添加标替换excel内容,修改颜色,合并单元格...。
需求要求:业务人员有个非常复杂得excel表格,各种表头等,但是模板是固定得。当然也可以实现在excel上搞出各种表格,但是不如直接用已有模板替换其中要动态得内容方便,这里我们用到CSDN得 xlsx-populate 插件。 实列中我…...
分布式大语言模型服务引擎vLLM论文解读
论文地址:Efficient Memory Management for Large Language Model Serving with PagedAttention 摘要 大语言模型(LLMs)的高吞吐量服务需要一次对足够多的请求进行批处理。然而,现有系统面临困境,因为每个请求的键值…...
如何开发一个大模型应用?
1. 背景 AIGC技术的突破性进展彻底改变了技术开发的范式,尤其是以GPT为代表的LLM,凭借其强大的自然语言理解与生成能力,迅速成为全球科技领域的焦点。2023年末,随着ChatGPT的爆火,AIGC技术从实验室走向规模化应用&…...
01-零基础入门嵌入式系统
1.什么是嵌入式系统 首先我们要知道计算机系统分为大型机、通用计算机和嵌入式系统三大类。 计算机系统的发展,经历了由1台计算机系统为N个人服务的大型机时代到由1台计算机系统为1个人服务的PC时代,正在步入由N台计算机系统为1个人服务的嵌入式时代。 嵌…...
【机器学习】CNN与Transformer的表面区别与本质区别
仅供参考 表面区别 1. 结构和原理: CNN:主要通过卷积层来提取特征,这些层通过滑动窗口(卷积核)捕捉局部特征,并通过池化层(如最大池化)来降低特征的空间维度。CNN非常适合处理具有网格状拓扑结构的数据,如图像。Transformer:基于自注意力(Self-Attention)机制,能…...
[数据结构]二叉搜索树详解
目录 一、二叉搜索树的概念 二、二叉搜索树的性能分析 三、二叉搜索树的中序遍历用于排序去重 四、二叉搜索树的查找 1、查找的非递归写法 2、查找的递归写法 五、二叉搜索树的插入 1、插入的非递归写法 2、插入的递归写法 六、二叉搜索树的删除 1、删除的非递归写法…...
撕碎QT面具(2):groupBox内容居中显示
问题描述: 当笔者在GroupBox中使用Form Layout构建图中内容时,不能居中显示。 解决方案: 1、首先在form layout左右添加横向弹簧,并ctrl进行选中这三个控件。点击水平布局,让中间的控件不变形。 2、选中groupBox&#…...
SpringBoot速成(14)文件上传P23-P26
1. 什么是 multipart/form-data? 想象一下,你有一个包裹要寄给朋友,但包裹里有不同类型的东西:比如一封信(文字)、一张照片(图片)和一个小礼物(文件)。为了确…...
图论入门算法:拓扑排序(C++)
上文中我们了解了图的遍历(DFS/BFS), 本节我们来学习拓扑排序. 在图论中, 拓扑排序(Topological Sorting)是对一个有向无环图(Directed Acyclic Graph, DAG)的所有顶点进行排序的一种算法, 使得如果存在一条从顶点 u 到顶点 v 的有向边 (u, v) , 那么在排序后的序列中, u 一定…...
