一、Lua的介绍

Lua 语音是由巴西里约热内卢天主教大学 ([Pontifical Catholic University of Rio de janeiro ) 里的一个研究小组与 1993年开发的一种轻量小巧的脚本(弱语言)语言,用标准 C 语音编写,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。

作为一种扩展语言,Lua 没有“主”程序的概念:它嵌入在宿主客户端中运行,称为嵌入程序或简称为宿主。(通常这个宿主是单机lua程序。) 宿主程序可以调用函数执行一段Lua代码,可以读写Lua变量,可以注册Lua代码调用的C函数。通过使用 C 函数,可以增强 Lua 以应对广泛的不同领域,从而创建共享语法框架的定制编程语言。

Lua适合一些简单的功能,不适合大量功能模块开发,Lua因为本身比较小巧,所以在开发会带来一些缺陷,比如测试的需要基于基于web环境 。

官网:http://www.lua.org/

二、环境配置

Lua 是基于 Lualuaiit的环境运行的,安装方式有很多中,可以直接在系统配置lua的运行时环境,也可以基于 IDE 的方式使用。

2.1 系统环境安装

(1)windwos安装

下载地址 : https://luabinaries.sourceforge.net/

  • 1.下载 lua-5.4.2_Win64_bin.zip 文件

  • 2. 将文件解压。

  • 3. 将解压后的文件到一个没有中文路径的盘符下,如 : D:/Lua

  • 4. 配置环境变量 右击此电脑 => 属性 => 高级系统设置=> 环境变量 => 系统变量 or 用户变量 => Path 里面添加上 lua文件

  • 5.测试 cmd => lua 54

(2)linux安装


curl -R -O http://www.lua.org/ftp/lua-5.3.0.tar.gz
tar zxf lua-5.3.0.tar.gz
cd lua-5.3.0
make linux test
make install

执行到sudo make linux test报错fatal error: readline/readline.h: No such file or directory

因为这个问题是缺少readline相关的库才导致的,遂安装libreadline-dev

yum install readline-devel

默认装在了 /usr/local/lib下。

2.2 基于idea安装

EmmyLua插件

https://github.com/EmmyLua/IntelliJ-EmmyLua

https://emmylua.github.io/zh_CN/

LDT 基于eclipse

https://www.eclipse.org/ldt/

2.3 内嵌式

比如在使用 Nginx的 openresty时就不需要配置,openresty内嵌了。

三、Lua 基础语法

3.1 交互式编程

Lua 提供了交互式变成模式,我们可以在命令行中输入程序代码并立刻看到效果

Lua 交互式编程模式可以通过命令 lua -i 或 lua 启动

3.2 脚本式编程

我们可以将 Lua 程序代码保存到一个以 lua 结尾的文件,并执行,该模式称为脚本式编程,如我们将如下代码存储在名为 hello.lua 的脚本文件中:


print("Hello world !")

我们也可以将代码修改为如下形式来执行脚本(在开头添加:#!/usr/local/bin/lua):

#!/usr/local/bin/luaprint("Hello World!")

3.3 注释

-- 两个减号是行注释--[[这是块注释这是块注释.--]]        

3.4 标识符

Lua 标示符用于定义一个变量,函数获取其他用户定义的项。标示符以一个字母 A 到 Z 或 a 到 z 或下划线 _ 开头后加上 0 个或多个字母,下划线,数字(0 到 9)。

最好不要使用下划线加大写字母的标示符,因为Lua的保留字也是这样的。

Lua 不允许使用特殊字符如 @, $, 和 % 来定义标示符。 Lua 是一个区分大小写的编程语言。因此在 Lua 中 Runoob 与 runoob 是两个不同的标示符。以下列出了一些正确的标示符:

mohd         zara      abc     move_name    a_123
myname50     _temp     j       a23b9        retVal

3.5 关键字

以下列出了 Lua 的保留关键词。保留关键字不能作为常量或变量或其他用户自定义标示符:

and

break

do

else

elseif

end

false

for

function

if

in

local

nil

not

or

repeat

return

then

true

until

while

goto

一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。

四、Lua的数据类型

Lua 是动态类型语言,变量不要类型定义,只需要为变量赋值。 值可以存储在变量中,作为参数传递或结果返回。

Lua 中有 8 个基本类型分别为:nil、boolean、number、string、userdata、function、thread 和 table。

数据类型

描述

nil

这个最简单,只有值nil属于该类,表示一个无效值(在条件表达式中相当于false)。

boolean

包含两个值:false和true。

number

表示双精度类型的实浮点数

string

字符串由一对双引号或单引号来表示

function

由 C 或 Lua 编写的函数

userdata

表示任意存储在变量中的C数据结构

thread

表示执行的独立线路,用于执行协同程序

table

Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字、字符串或表类型。在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。

可以通过 type函数来测试变量或值的类型:

print(type("Hello world"))      --> string
print(type(10.4*3))             --> number
print(type(print))              --> function
print(type(type))               --> function
print(type(true))               --> boolean
print(type(nil))                --> nil
print(type(type(X)))            --> string

4.1 数字类型

Lua的数字只有double型,64bits

你可以以如下的方式表示数字


num = 1024num = 3.0num = 3.1416num = 314.16e-2num = 0.31416E1num = 0xffnum = 0x56

4.2 字符串

也可以使用转义字符‘\n’ (换行), ‘\r’ (回车), ‘\t’ (横向制表), ‘\v’ (纵向制表), ‘\’ (反斜杠), ‘\”‘ (双引号), 以及 ‘\” (单引号)等等

下面的四种方式定义了完全相同的字符串(其中的两个中括号可以用于定义有换行的字符串)

字符串由一对双引号或单引号来表示。

a = 'alo\n123"'a = "alo\n123\""a = '\97lo\10\04923"'a = [[alo123"]]

也可以用 2 个方括号 "[[]]" 来表示"一块"字符串。

html = [[
<html>
<head></head>
<body><a href="www.baidu.com/">baidu</a>
</body>
</html>
]]
print(html)

在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字:

> print("2" + 6)
8.0
> print("2" + "6")
8.0
> print("2 + 6")
2 + 6
> print("-2e2" * "6")
-1200.0# 一下报错因为字符串连接 使用 ..
> print("error" + 1)
stdin:1: attempt to perform arithmetic on a string value
stack traceback:stdin:1: in main chunk[C]: in ?
>

字符串之间连接

.. 作为连接符

print("name:" .. "zs")

使用 # 来计算字符串字节的长度(一个中文算两个字节),放在字符串前面,如下实例:

> len = "www.baidu.com"
> print(#len)
14
> print(#"www.baidu.com")
14
>

4.3 table(表)

在 Lua 里,table 的创建是通过"构造表达式"来完成,最简单构造表达式是{},用来创建一个空表。也可以在表里添加一些数据,直接初始化表:

-- 创建一个空的 table
local tbl1 = {}-- 直接初始表
local tbl2 = {"apple", "pear", "orange", "grape"}

Lua 中的表(table)其实是一个"关联数组"(associative arrays),数组的索引可以是数字或者是字符串。

-- table_test.lua 脚本文件
a = {}
a["key"] = "value"
key = 10
a[key] = 22
a[key] = a[key] + 11
for k, v in pairs(a) doprint(k .. " : " .. v)
end-- 一个table 中是可以以数字和字符串为下标,也可以配合使用但是配置使用的话,又可以把字符串的下标
-- 看做是属性。
a = {"22","233"}
a["key"] = "value"for k, v in pairs(a) doprint(k .. ":".. v)
end--[[
结果 :1:222:233key:value
1]]

不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。

-- table_test2.lua 脚本文件
local tbl = {"apple", "pear", "orange", "grape"}
for key, val in pairs(tbl) doprint("Key", key)
end

table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。

-- table_test3.lua 脚本文件
a3 = {}
for i = 1, 10 doa3[i] = i
end
a3["key"] = "val"
print(a3["key"])
print(a3["none"])

4.4 function

在 Lua 中,函数是被看作是"第一类值(First-Class Value)",函数可以存在变量里。

-- function_test.lua 脚本文件
function factorial1(n)if n == 0 thenreturn 1elsereturn n * factorial1(n - 1)end
end
print(factorial1(5))
-- 将函数 复制给另一个函数
factorial2 = factorial1print(factorial2(5))--[[结果 :120120
]]

function 可以以匿名函数(anonymous function)的方式通过参数传递:

-- 参数为function 匿名函数
function doSome(tab,fun)for i,v in pairs(tab) do-- 调用传递过来的匿名函数fun(i,v);end
end
array= {1,2,3,4}
doSome(array,function(i,v)print("下标: "..i.." : ".."值:"..v)
end)

4.5 nil (空)

nil 作比较时应该加上双引号 ":

> type(X)
nil
> type(X)==nil
false
> type(X)=="nil"
true
>
-- type(X)==nil 结果为 false 的原因是 type(X) 实质是返回的 "nil" 字符串,是一个 string 类型:
type(type(X))==string

nil 类型表示一种没有任何有效值,它只有一个值 -- nil,例如打印一个没有赋值的变量,便会输出一个 nil 值:

print(a)

对于全局变量和 table,nil 还有一个"删除"作用,给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉,执行下面代码就知:

list = {key1 = "1",key2="2",key3="3"}
for k ,v in pairs(list) doprint(k ..":" .. v )
end
-- 将key1 删除
list.key1=nil
for k ,v in pairs(list) doprint(k ..":" .. v )
end

4.6 boolean

boolean 类型只有两个可选值:true(真) 和 false(假),Lua 把 false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true:

4.7 thread

在 Lua 里,最主要的线程是协同程序(coroutine)。它跟线程(thread)差不多,拥有自己独立的栈、局部变量和指令指针,可以跟其他协同程序共享全局变量和其他大部分东西。

线程跟协程的区别:线程可以同时多个运行,而协程任意时刻只能运行一个,并且处于运行状态的协程只有被挂起(suspend)时才会暂停。

4.8 userdata

userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。

五、变量

变量在使用前,需要在代码中进行声明,即创建该变量。

编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。

Lua 变量有三种类型:全局变量、局部变量、表中的域。

全局变量是在同一模块内可以互通使用。

Lua 中的变量全是全局变量,哪怕是语句块或是函数里,除非用 local 显式声明为局部变量。

局部变量的作用域为从声明位置开始到所在语句块结束。

变量的默认值均为 nil。


a = 5               -- 全局变量
local b = 5         -- 局部变量function joke()c = 5           -- 全局变量local d = 6     -- 局部变量
endjoke()
print(c,d)          --> 5 nildolocal a = 6     -- 局部变量b = 6           -- 对局部变量重新赋值print(a,b);     --> 6 6
endprint(a,b)      --> 5 6

当变量个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略:

a. 变量个数 > 值的个数             按变量个数补足nil
b. 变量个数 < 值的个数             多余的值会被忽略

5.1 索引

对 table 的索引使用方括号 []。Lua 也提供了 . 操作。

t[i]
t.i                 -- 当索引为字符串类型时的一种简化写法
gettable_event(t,i) -- 采用索引访问本质上是一个类似这样的函数调用

六、流程控制

Lua 编程语言流程控制语句通过程序设定一个或多个条件语句来设定。在条件为 true 时执行指定程序代码,在条件为 false 时执行其他指定代码。

以下是典型的流程控制流程图:

控制结构的条件表达式结果可以是任何值,Lua认为false和nil为假,true和非nil为真。

要注意的是Lua中 0 为 true:

--[ 0 为 true ]
if(0)
thenprint("0 为 true")
end-- 结果: 0 为 true 

Lua 提供一下控制结构语句功能:

if 语句

if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。

if...else 语句

if 语句 可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码。

if 嵌套语句

你可以在if 或 else if中使用一个或多个 if 或 else if 语句

6.1 if语句

Lua if 语句 由一个布尔表达式作为条件判断,其后紧跟其他语句组成。

if(布尔表达式)
then--[ 在布尔表达式为 true 时执行的语句 --]
end--- 实例 -----------[ 定义变量 --]
a = 10;--[ 使用 if 语句 --]
if( a < 20 )
then--[ if 条件为 true 时打印以下信息 --]print("a 小于 20" );
end
print("a 的值为:", a);

6.2 if..else

Lua if 语句可以与 else 语句搭配使用, 在 if 条件表达式为 false 时执行 else 语句代码块。

Lua if...else 语句语法格式如下:

if(布尔表达式)
then--[ 布尔表达式为 true 时执行该语句块 --]
else--[ 布尔表达式为 false 时执行该语句块 --]
end-----------------------实例-------------------------------
--[ 定义变量 --]
a = 100;
--[ 检查条件 --]
if( a < 20 )
then--[ if 条件为 true 时执行该语句块 --]print("a 小于 20" )
else--[ if 条件为 false 时执行该语句块 --]print("a 大于 20" )
end
print("a 的值为 :", a)

6.3 if嵌套

Lua if 语句允许嵌套, 这就意味着你可以在一个 if 或 else if 语句中插入其他的 if 或 else if 语句。

if( 布尔表达式 1)
then--[ 布尔表达式 1 为 true 时执行该语句块 --]if(布尔表达式 2)then--[ 布尔表达式 2 为 true 时执行该语句块 --]end
end-------------示例-------------------[ 定义变量 --]
a = 100;
b = 200;--[ 检查条件 --]
if( a == 100 )
then--[ if 条件为 true 时执行以下 if 条件判断 --]if( b == 200 )then--[ if 条件为 true 时执行该语句块 --]print("a 的值为 100 b 的值为 200" );end
end
print("a 的值为 :", a );
print("b 的值为 :", b );
local function main()local age = 140local sex = 'Male'if age == 40 and sex =="Male" thenprint(" 男人四十一枝花 ")elseif age > 60 and sex ~="Female" thenprint("old man!!")elseif age < 20 thenio.write("too young, too simple!\n")elseprint("Your age is "..age)endend-- 调用
main()

七、循环

很多情况下我们需要做一些有规律性的重复操作,因此在程序中就需要重复执行某些语句。

一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件。

循环结构是在一定条件下反复执行某段程序的流程结构,被反复执行的程序被称为循环体。

循环语句是由循环体及循环的终止条件两部分组成的。

7.1 控制语句

循环控制语句用于控制程序的流程, 以实现程序的各种结构方式。

Lua 支持以下循环控制语句:

控制语句

描述

break 语句

退出当前循环或语句,并开始脚本执行紧接着的语句。

goto 语句

将程序的控制点转移到一个标签处。

(1)break 语句

Lua 编程语言 break 语句插入在循环体中,用于退出当前循环或语句,并开始脚本执行紧接着的语句。

如果你使用循环嵌套,break语句将停止最内层循环的执行,并开始执行的外层的循环语句。

break

实例

以下实例执行 while 循环,在变量 a 小于 20 时输出 a 的值,并在 a 大于 15 时终止执行循环:

--[ 定义变量 --]
a = 10--[ while 循环 --]
while( a < 20 )
doprint("a 的值为:", a)a=a+1if( a > 15)then--[ 使用 break 语句终止循环 --]breakend
end

(2)goto

Lua 语言中的 goto 语句允许将控制流程无条件地转到被标记的语句处。

这个需要提前打好标记,再能跳转。

语法有问题

语法:

goto Lable -- Lable 的格式
:: Lable :: 

7.2 循环

Lua 语言提供了以下几种循环处理方式:

循环类型

描述

while 循环

在条件为 true 时,让程序重复地执行某些语句。执行语句前会先检查条件是否为 true。

for 循环

重复执行指定语句,重复次数可在 for 语句中控制。

repeat...until

重复执行循环,直到 指定的条件为真时为止

循环嵌套

可以在循环内嵌套一个或多个循环语句(while do ... end;for ... do ... end;repeat ... until;)

(1)while循环

while(condition)
dostatements
end

statements(循环体语句) 可以是一条或多条语句,condition(条件) 可以是任意表达式,在 condition(条件) 为 true 时执行循环体语句。

local i = 0local max = 10while i <= max doprint(i)i = i +1end

(2)for循环

Lua 编程语言中 for 循环语句可以重复执行指定语句,重复次数可在 for 语句中控制。

Lua 编程语言中 for语句有两大类::

  • 数值for循环

  • 泛型for循环

for var=exp1,exp2,exp3 do  <执行体>
end  
for i=1,f(x) doprint(i)
endfor i=10,1,-1 doprint(i)
end

for的三个表达式在循环开始前一次性求值,以后不再进行求值。比如上面的f(x)只会在循环开始前执行一次,其结果用在后面的循环中。

验证如下:

#!/usr/local/bin/lua
function f(x)  print("function")  return x*2
end
for i=1,f(5) do print(i)
end

泛型for循环

泛型 for 循环通过一个迭代器函数来遍历所有值,类似 java 中的 foreach 语句。

Lua 编程语言中泛型 for 循环语法格式:

ipairs :进行循环的时候要求 下标是数组,否则循环不到

pairs :可以循环任意类型的下标数组。

--打印数组a的所有值
a = {"one", "two", "three"}
for i, v in ipairs(a) doprint(i, v)
end 

(3)repeat...until 循环

Lua 编程语言中 repeat...until 循环语句不同于 for 和 while循环,for 和 while 循环的条件语句在当前循环执行开始时判断,而 repeat...until 循环的条件语句在当前循环结束后判断。

repeatstatements
until( condition )
--[ 变量定义 --]
a = 10
--[ 执行循环 --]
repeatprint("a的值为:", a)a = a + 1
until( a > 15 )

八、函数

在Lua中,函数是对语句和表达式进行抽象的主要方法。既可以用来处理一些特殊的工作,也可以用来计算一些值。

Lua 提供了许多的内建函数,你可以很方便的在程序中调用它们,如print()函数可以将传入的参数打印在控制台上。

Lua 函数主要有两种用途:

  • 1.完成指定的任务,这种情况下函数作为调用语句使用;

  • 2.计算并返回值,这种情况下函数作为赋值语句的表达式使用。

8.1 闭包和upvalue

首先 闭包和 upvalue 的是一种概念。

闭包就是能够读取其他函数内部变量的函数。

例如在JavaScript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数”。在本质上,闭包是将函数内部的和函数外部连接的桥梁。

Lua

当一个函数内部签到另一个函数定义时,内部的函数可以访问外部的局部变量,这种特征在lua中我们称作词法定界。

Lua 会将函数的局部变量和其使用到的非局部变量存储在一个称为“upvalue”的结构中。当函数执行时,它可以访问这些非局部变量,即使这些变量在函数执行时已经不再存在。

虽然这种看起来很清楚,事实并非如此,词法定界加上第一类函数在编程语言中是一个强大的概念,很少语言提供这种支持。

-- 一下就是一个闭包函数
function newCounter()local i = 0 return function()     -- anonymous functioni = i + 1return iend
endc1 = newCounter()print(c1())  --> 1print(c1())  --> 2print(c1())----------
function fun1(x,y) local a = 1 ;  -- 类似于静态变量 upValuereturn function()a = a+1 ;print(a,x,y)return aend
endfun= fun1(1,2)
print(fun())
print(fun())
print(fun())

upvalue是让lua来模拟实现,类似c语言中,静态变量机制的一种机制。一个带上upvalue的函数,我们称之为闭包(closure)。一个c函数,带上upvalue的结构,我们称之为c闭包。而一个lua函数,带上upvalue,我们称之为lua闭包。我们可以看一下官方对于upvalue相关内容的阐述。

在 Lua 中,Upvalue(上值)指的是在闭包中使用的外部局部变量。具体来说,当一个函数嵌套在另一个函数中时,它可以访问其父函数的局部变量。在 Lua 中,这些局部变量被称为Upvalue。
当一个函数返回时,它的局部变量通常会被释放,但是如果有内部函数(即闭包)使用了这些变量,那么它们就会被存储在该闭包的Upvalue中,以便在闭包被调用时仍然可以访问它们。

local upval = 1
local upval2 = 2
function test()local locvar = 3print(upval)local function aaa()print(upval+upval2+locvar)endaaa()
end--[[
上面这个例子中,test函数的外层,一共有两个变量,upval和upval2。
test函数内,有一行打印upval的代码,因为有这个操作,test函数需要引用到外层函数的upval这个变量,
因此upval是test函数的一个upvavle。而上面这个例子,在test函数内,
又定义了一个aaa函数,在aaa函数内,因为使用了upval、upval2和locvar几个变量,
因此aaa函数的upvalue有upval、upval2和locvar。由于aaa是test的内层定义的函数,
test是aaa的外层函数,因此test函数的upvalue也包括了,upval、upval2。现在,
只是给大家一个直观的概念,其实很多读者对此已经耳熟能详了,在后面的章节内容中,
我会更细致地论述这个机制的原理。

8.2 函数定义

Lua 编程语言函数定义格式如下:

optional_function_scope function function_name( argument1, argument2, argument3..., argumentn)function_bodyreturn result_params_comma_separated
end

解析:

  • optional_function_scope:

  • 该参数是可选的指定函数是全局函数还是局部函数,未设置该参数则为全局函数,如果需要设置为局部函数则 需要使用 local 关键字 。

  • function_name :

  • 指定函数,可以是匿名函数

  • argument1, argument2 ....

  • 函数参数,多个参数之间使用 , 割开 ,也可以不带参数

  • function_body :

  • 函数体,函数中需要执行的代码块语句

  • result_params_comma_separated:

  • 函数返回值,Lua 语言支持多结果返回 ,多值之间使用,割开。

-------------Lua 中我们可以将函数作为参数传递给函数,如下实例:-------------------
myprint = function(param)print("这是打印函数 -   ##",param,"##")
endfunction add(num1,num2,functionPrint)result = num1 + num2-- 调用传递的函数参数functionPrint(result)
end
myprint(10)
-- myprint 函数作为参数传递
add(2,5,myprint)

8.3 多值返回

Lua函数可以返回多个结果值,比如string.find,其返回匹配串"开始和结束的下标"(如果不存在匹配串返回nil)。

 startIndex, endIndex = string.find("www.runoob.com", "runoob")
print(startIndex, endIndex)
5    10

Lua函数中,在return后列出要返回的值的列表即可返回多值,如:

function maximum (a)local mi = 1             -- 最大值索引local m = a[mi]          -- 最大值for i,val in ipairs(a) doif val > m thenmi = im = valendendreturn m, mi
endprint(maximum({8,10,23,12,5}))

8.4 可变参数

Lua 函数可以接收可变数量的参数,和 java 的可变参数很想,在函数裂变中使用三点 ...表示函数有可变的参数 。

function add(...)
local s = 0  for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  s = s + v  end  return s
end
print(add(3,4,5,6,7))  --->25

我们也可以通过 select("#",...) 来获取可变参数的数量:

function average(...)result = 0local arg={...}for i,v in ipairs(arg) doresult = result + vendprint("总共传入 " .. select("#",...) .. " 个数")return result/select("#",...)
endprint("平均值为",average(10,5,3,4,5,6))

有时候我们可能需要几个固定参数加上可变参数,固定参数必须放在变长参数之前:

function fwrite(fmt, ...)  ---> 固定的参数fmtreturn io.write(string.format(fmt, ...))
endfwrite("runoob\n")       --->fmt = "runoob", 没有变长参数。
fwrite("%d%d\n", 1, 2)   --->fmt = "%d%d", 变长参数为 1 和 2

常在遍历变长参数的时候只需要使用 {…},然而变长参数可能会包含一些 nil,那么就可以用 select 函数来访问变长参数了:select('#', …) 或者 select(n, …)

  • select('#', …) 返回可变参数的长度。

  • select(n, …) 用于返回从起点 n 开始到结束位置的所有参数列表。

调用 select 时,必须传入一个固定实参 selector(选择开关) 和一系列变长参数。如果 selector 为数字 n,那么 select 返回参数列表中从索引 n 开始到结束位置的所有参数列表,否则只能为字符串 #,这样 select 返回变长参数的总数。

function f(...)a = select(3,...)  -->从第三个位置开始,变量 a 对应右边变量列表的第一个参数print (a)print (select(3,...)) -->打印所有列表参数
endf(0,1,2,3,4,5)

注意事项:
如果,没有"尾调用消除" 的话,每次用户的移动会创建一个新的 stack ,若干步之后就有可能导致栈移除的风险 。
在Lua 中支持这样一种 函数调用的优化,即" 尾调用消除"。我们可以将这种函数方式是为 goto 语句 ,
如:function f (x) return g(x) end
由于g(x) 函数 是f(x) 的最后一条语句,在函数 g 返回之后,f() 函数将没有任何指令需要被执行,因此在函数g() 返回时,可以直接返回到 f() 函数的调用点。由此可见,Lua 解释器一旦发现 g() 函数的尾调用,那么在调用 g() 是将不会产生音函数调用而引擎的栈开销。这里需要强调的是,尾调用函数一定是其调用函数的最后一条语句,否则 Lua 不会进行优化。然而事实上,我们在很多看似是尾调用的场景中,并不是真正的为尾调用,如:
function f(x) g(x) end -- 没有return语句的明确提示
function f(x) return g(x) +1 -- 在 g() 函数返回之后让扔需要执行一次加一的指令。
function f(x) return x or g(x) -- 如果g() 函数返回多个值,该操作会强制要求 g() 函数只返回一个值。
function f(x) return (g(x)) --原因同上。
在Lua中,只有 "return <func>(<args>) " 形式才是标准的尾调用,至于参数中的(args) 是否包含表达式,由于表达式的执行是在函数调用之前完成的,隐藏不会应函数成为尾掉函数9 数组

数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。

Lua 数组的索引键值可以使用整数表示,数组的大小不是固定的。

九、数组

9.1 一维数组

一维数组是最简单的数组,其逻辑结构是线型表。一维数组可以使用for循环出数组中的元素 。如下实例:

-- 一维数组的声明遍历
oneArr = {"张三",12,33};
print("数组长度".. " : " .. #oneArr)
for i=1,#oneArr,1 doprint(oneArr[i])
end

9.2


-- 二维数组的声明遍历towArr = {}
-- 初始化二维数组 3*3 的
for i=1,3 dotowArr[i] = {}for j = 1, 3 dotowArr[i][j] = i* j;end
end-- 遍历二维数组
for i =1,#towArr dofor j = 1,#towArr[i] doprint(towArr[i][j])end
end

本文章用于学习笔记使用。

参考一下文章

https://www.runoob.com/lua/lua-tables.html

Lua 入门详情讲解相关推荐

  1. Openresrt最佳案例 | 第2篇:Lua入门

    什么是lua Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴西里约热内卢天主教大学(Po ...

  2. Github入门详情教程

    前言 之前我写了一篇文章<一篇文章了解Github和Git教程>还延伸了几篇阅读,对大部分小白很有用,那么我继续普及下Github页面及其概念. 定义 GitHub 是一个网站,一个面向开 ...

  3. Vue全家桶入门精细讲解

    Vue入门精细讲解 感谢coderwhy老师的精心讲解,本笔记全部内容源于coderwhy老师的课堂笔记: 一. Hello Vuejs 1.1. 认识Vuejs 为什么学习Vuejs 可能你的公司正 ...

  4. 跟着王进老师学开发Python篇:基础入门案例讲解-王进-专题视频课程

    跟着王进老师学开发Python篇:基础入门案例讲解-166人已学习 课程介绍         共计45个项目案例+项目源码,跟着王进老师尽情玩转Python解释器! 本课程涉及Python的基础语法, ...

  5. 和与余数的和同余理解_5 同余 ——数论入门知识讲解系列

    数学竞赛 数论是纯粹数学的分支之一,主要研究整数的性质,按研究方法分为初等数论和高等数论.中学生(甚至小学生)课外数学兴趣小组的许多内容是属于初等数论的,各级别数学竞赛也会把初等数论作为重点内容进行考 ...

  6. linux Shell(脚本)编程入门实例讲解详解

    linux Shell(脚本)编程入门实例讲解详解 为什么要进行shell编程 在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活的工具.Shell不仅仅是命令的收集, ...

  7. 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world...

    2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...

  8. c语言基础编程题讲解,C语言入门例题讲解

    C语言入门例题讲解 C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的'编程语言.今天就为大家 ...

  9. bower安装使用入门详情

    bower安装使用入门详情 bower自定义安装: 安装bower需要先安装node,npm,git 全局安装bower,命令:npm install -g bower 进入项目目录下,新建文件1.t ...

最新文章

  1. AngularJs $cacheFactory 缓存服务
  2. matlab 两列数据相乘,在EXCEL中,两列完全相同的数据,求和结果不一样??单元格两列相乘的公式...
  3. Nginx的server为0.0.0.0/0.0.0.1的作用?
  4. 前端那些事之原生 js实现贪吃蛇篇
  5. WORD如何创建三线表样式?
  6. 变速恒频风电机组的优缺点_保障风电齿轮箱的有效润滑
  7. loadRunner函数之lr_set_debug_message
  8. Spring MVC--@RequestMapping
  9. 中建股份400亿大型IPO获“特批”
  10. 冒泡排序 图解+python实现
  11. 一 ARM9(S3C2440)的中断系统——理论知识
  12. 页面提交时,显示“提交中”等待效果
  13. IDEA 从入门到踩坑(4)-No tests found for given includes 错误解决
  14. 关于破解ewebeditor V10.9 编辑器的问题
  15. AR、BR、CR、SR 与 CE、PE、P概念整理
  16. 陕西中际现代:基于自适应算法的PLC滴灌控制系统
  17. 如何使用Sketch绘制半个圆角矩形
  18. 少即是多:视觉SLAM的点稀疏化(IROS 2022)
  19. html热区坐标,HTML之六:图像的热区连接
  20. BigBrother的大数据之旅Day 12 Hbase(1)

热门文章

  1. 勃仔诞生记:Hubbleverse哈勃元宇宙的起源故事
  2. 【微服务架构】一文读懂单片到微服务架构的模式和最佳实践
  3. 干饭人的苦恼:科学家发现人的饥饿感和孤独感非常相似
  4. 教师计算机基础教学考核制度,ArticleView
  5. Angular 9.1.0在项目路径包含软链接时编译某些包时报错,9.1.1已修正
  6. 对一个windows2000注册表项的粗略分析(转)
  7. 生命是一种长期而持续的累积 - 台湾清华彭明辉老师 [转]
  8. Python+Excel:将一个工作簿拆分为多个工作簿
  9. discuz如何关闭个人空间
  10. TrajGRU降雨量预测: 一个基准和一个新的模型