Lua 学习笔记(自用)

Lua 学习笔记

1 语言基础

运行方式类似Python,可以直接在交互行运行,也可以通过解释器运行某个脚本。也可以在交互行运行某个lua脚本

dofile("hello.lua")  -- 在交互行运行某个文件

1.1 标识符

标识符规则与C语言一样。任意字母、数字和下划线组成的字符串,不以数字开头。

“下画线+大写字母”(例如_VERSION)组成的标识符通常被Lua 语言用作特殊用途,应避免将其用作其他用途。

保留字 (C语言没有的)

  • function
  • in
  • local
  • then
  • repeat
  • until
  • not
  • or
  • end

1.2 注释

-- 一行注释

--[[                    
   print("多行注释")
   print("多行注释")
   print("多行注释")
--]]

---[[
   print("快速取消注释")
   print("取消注释")
   print("取消注释")
--]] 

1.3 变量

类似python。动态类型语言(Dynamically-typed language),在这种语言中;没有类型定义,每个值都带有自身的类型信息。

  • 变量没有类型,任何变量可以指向任何类型的值

  • 动态回收,无类型

  • 未经初始化,值为nil

  • 当把nil赋值给全局变量时,Lua会回收该全局变量

  • Lua语言不区分未初始化变量和被赋值为nil的变量。

Lua语言中有8种基本类型: nil (空)、 boolean (布尔)、 number (数值)、 string (字符串)、 userdata (用户数据)、 function (函数)、 thread (线程)和 table (表)。使用函数 type可获取一个值对应的类型名称:

1.4 nil

  • nil是一种只有一个nil值的类型,它的主要作用就是与其他所有 值进行区分。

  • Lua语言使用nil来表示无效值(non-value,即没有有用 的值)的情况。

  • 一个全局变量在第一次被赋 值前的默认值就是nil,而将nil赋值给全局变量则相当于将其删除。

1.5 Boolen

  • Boolean类型具有两个值, true 和 false ,它们分别代表了传 统布尔值。

  • 将除Boolean值 falsenil 外的所有其他值视为真

  • 特别的是,在条件检测中Lua语言把零和空字符串也都视为真。

  • 逻辑预算符号 像python and or not 。都遵循短路求值

  • not 运算符,永远返回Boolean类型的值。类似C语言
x = x or v

if not x then x = v end  -- 当 x 未被初始化时,将其默认值设为v (假设 x 不是Boolean类型的 false

1.6 独立解释器

#!/usr/bin/lua    -- 然后 chmod + x  hello.lua
#!/usr/bin/env  lua  -- 也可
选项 实例 效果
- e lua -e "print(maht.sin(19))" 允许我们直接在命令行输入代码
- i lau -i hello.lua 运行完其他命令行参数后,进入交互模式
- l lua -llib -i -e "x=10" 下面的命令会首先加载lib 库,然后执行x=10的赋值语句,并最终进入交互式模式

1.7 特殊环境变量

  • 解释器在处理参数前,会查找名为LUA_INIT_5_3的环境变量
  • 如果找不到,就会再查找名为LUA_INIT的环境变量。
  • 如果这两个环境变 量中的任意一个存在,并且其内容为@ filename ,那么解释器就会运 行相应的文件
  • 若不以@开 头,那么解释器就会认为其包含Lua代码,并会对其进行解释执行

1.8 命令行参数

lua -e "print(1)"  script a b
--[[
	arg[0] = "script"
	arg[1] = "a"
	arg[2] = "b"
	arg[-1] = "print(1)"
	arg[-2] = "-e"
	agr[-3] = "lua"
]]

2 数值

从Lua 5.3版本开始,Lua语言为数值格式提供了两种选择:被称 为 integer 的64位整型和被称为 float 的双精度浮点类型(注意, 在本书中“float”不代表单精度类型)。对于资源受限的平台,我们 可以将Lua 5.3编译为精简 Lua ( Small Lua )模式,在该模式中使 用32位整型和单精度浮点类型。

2.1 字面量

4
0.4
4.57e-3  -- 0.00457
0.3e5    -- 30000
0.3E5    -- 同上
0xff  -- 255
-- 十六进制浮点小数
0x0.2  -- 0.125
0x1p-1  -- p后面跟上指数部分 == 1 * 2^-1
0xa.bp2  -- 42.75 == a.b * 2^2 == 10.6875 * 4

整数型和浮点型的类型都是 number ,可以相互转换

1 == 1.0  -- true
-3 == -3.0 -- true
0.2e3 == 200 --ture

需要区分整数值和浮点型值时

math.type(3)  -- integer
math.type(3.0) -- float

十六进制转换输出

string.format("%a",419)  -- 0x1.a3p+8

2.2 算数运算

如果两个操作数都是整型值,那么结果也是整型值;否则,结果 就是浮点型值。当操作数一个是整型值一个是浮点型值时,Lua语言会 在进行算术运算前先将整型值转换为浮点型值

除法运算

-- 除法运算操作的永远是浮点数且产生浮点型的结果
3 / 2 == 1.5
3 // 2 == 1 
3.0 // 2 == 1.0
-9 // 2 == -5

取模运算

a % b == a - ( ( a // b ) * b)

x = math.pi
x - x%0.01  -- 3.14
x - x%0.001  -- 3.141

幂运算

-- 操作数永远是浮点类型
2 ^ 2
2 ^ (-2)
2 ^ (0.5)
2 ^ (1/3)

2.3 关系运算

  • ==用于相等性测试,~=用于不等性测试。
  • 当这两个值的类型不同时,Lua语言认为它们是不相等的
  • 比较数值时应永远忽略数值的子类型,数值究竟是以整型还是浮 点型类型表示并无区别,只与算术值有关

2.4 数学库

math.random()  -- [0,1) 伪随机实数
math.random(n)  -- [1,n] 伪随机整数

在一个程序启动时,系统固定使用1为种子 初始化伪随机数发生器。如果不设置其他的种子,那么每次程序运行 时都会生成相同的伪随机数序列。

math.randomseed(os.time())  -- 设置伪随机发生器的种子

取整函数

math.floor()  -- 向下取整
math.ceil()   -- 向上取整
math.modf()   -- 向零取整, 返回整数部分和小数部分
math.floor(x+0.5) -- 四舍五入,x 是一个很大整数是可能出错


math.modf(3.3) -- 3  0.3
math.modf(-3.3) -- -3 -0.3

另 一 种 把 数 值 强 制 转 换 为 整 型 值 的 方 式 是 使 用 函 数 math.tointeger,该函数会在输入参数无法转换为整型值时返回nil:

> math.tointeger(-199)
-199
> math.tointeger(-199.1)
nil

向偶舍入(无偏取整)

function round(x)
    local f = math.floor(x)
    if ( x== f) or ( x % 2.0 == 0.5 ) then
        return f
    else
        return math.floor(x+0.5)
    end
end

整型最值

math.maxinteger
math.mininterger

2.4 tips

我们可以简单地通过增加0.0的方法将整型值强制转换为浮点型 值,一个整型值总是可以被转换成浮点型值:

3 + 0.0  --> 3.0

通过与零进行按位或运算,可以把浮点型值强制转换为整型值:

11.0 | 0  --> 11 
-- 11.1 | 0 抛出异常

小于2^53 (即9007199254740992)的所有整型值的表示与双精度 浮点型值的表示一样,对于绝对值超过了这个值的整型值而言,在将 其强制转换为浮点型值时可能导致精度损失:

> 9007199254740991 ==  9007199254740991 + 0.0
true
> 9007199254740992 ==  9007199254740992 + 0.0
true
> 9007199254740993 ==  9007199254740993 + 0.0
false

3 字符串

我们可以使用连接操作符..(两个点)来进行字符串连接。如果 操作数中存在数值,那么Lua语言会先把数值转换成字符串:

> "hello " .. 3   .. " ok "
hello 3 ok

多行字符

[[
    今天
    天气/n
    不错
]]
print(s)
kj
    今天
    天气/n
    不错

应对多行字符串中出现 ]]

-- 在[[、]] 之间加入若干=符号
s = [==[
    今天]]
    天气/n
    不错
]==]
print(s)

算术运算的规则就是只有在两个操作数都是整 型值时结果才是整型。因此,由于字符串不是整型值,所以任何有字 符串参与的算术运算都会被当作浮点运算处理:

> "100" + 1
101.0

字符串转数字

无法完成转换返回 nil

tonumber("11" , 2) -- 指明第一个参数的进制 结果3
tonumber("11")  -- 11

数字转字符串

tostring(10) == "10"  --> true

字符串API

> s = "abcd"
> string.len(s)
4
> string.rep(s,2)
abcdabcd
> s
abcd
> string.upper(s)
ABCD
> string.lower("ABC")
abc
> string.reverse("123")
321
> string.sub("12345",1,3)  -- 下标从1开始,[1,3] 前闭后闭
123

字符串待续

。。。。。。。。

4 表

类似python中的字典。任意类型除了nil都可以作为键,任何类型都可以为值。D

D[1] == D[1.0]  -- true
D = { "one ", "two" , "three" }
D = { [1] = "one", [20] = "two", ["3"] = three}

#

获取字符串、表长度

#D == 3
#"1234" == 4

遍历表

类似python,顺序无法确定

D = {
    "one", "two", "three"
}

for k,v in pairs(D) do
    print(k,v)
end

D = {
    "one",  "two", "three"
}

for i = 1, #D do
    print(D[i])
end

表标准库

t = {10,20,30}
table.insert(t,1,15)  -- t == {15,10,20,30}
table.insert(t, 100) -- 在最后插入

table.remove(t)  -- 删除最后一个
table.remove(t,2) -- 删除第二个

table.move(t, i, j, k)  -- 将表中t[i-j] 复制到下标K开始的(j-i+1)长的位置、返回指向表的变量
table.move(t,1,#a,1,{}) -- 返回一个指向第二个表的变量

函数

function f(a,b)
    print (a,b)
end

f()
f(1)
f(1,2)
f(1,2,3)

-- 不报错,少了就当nil;多了就看不见

nil     nil
1       nil
1       2
1       2

函数待续

posted @ 2022-07-04 19:24  orangeQWJ  阅读(139)  评论(0编辑  收藏  举报