lua 之 基础

环境: Mac, Lua 5.3.4

  • lua的常用数据类型:
nil, boolean, number, string, userdata, function, table, thread
  • 在lua中false,nil为假,其他为真

and中,如果第一个操作数为假,则返回第一个操作数,比如:

4 and 5     			-- 5      
nil and 6   			-- nil 
false and true 		    -- false 
true and nil 			-- nil 
{} and 1 			    -- 1

or中,如果第一个操作数为真, 则返回第一个操作数,比如:

true or false 		-- true 
nil or false	    -- false 
false or "hi"	    -- hi
0 or 5          	-- 0
{} or nil 		    -- table:...
  • 使用type判定类型:
print(type(10), type(10.3)) 		-- number, number 
print(type(nil))                    -- nil
print(type(type))                   -- function
print(type(type(nil)))              -- string
print(type({}))                     -- table

-- 在字符串参与算术运算时,都会被当作浮点数处理
-- 原因在于Lua存储字符串使用8bit存储
print("10" + 1)                     -- 11.0
print("10" .. 1)                    -- 101
print(10 .. 1)                      -- 101
  • 数值的表示是有长度限制的,标准Lua使用64bit来存储整型值,其最大值约等于10的19次方
print(math.mininteger) 	-- -9223372036854775808 最小
print(math.maxinteger) 	-- 9223372036854775807  最大
print(math.maxinteger + 1 == math.mininteger) 	-- true
print(math.mininteger - 1 == math.maxinteger) 	-- true
  • 对于比较操作,不会对操作数像算术运算那样实行强制转换,如果比较中混用字符串和数字会抛出异常
-- Error: attempt to compare number with string
print(2 < "14") 		
  • Lua语言中遍历的几种方式:

pairs: 遍历元素的出现顺序可能是随机的,但是遍历中的每个元素仅会出现一次

ipairs: 遍历元素按照顺序执行, 也就是索引+1, 直到遇到value为nil或者key+1没有的,就会暂停

-- 索引+1条件不符合
local tab = {"one", [3] = "three", [4] = "four"}
for i, v in ipairs(tab) do 
	print(i, v)                 -- 1 one
end 

-- value 存在nil
local tab = {"one", [3] = nil , "two", [4] = "four"}
for i, v in ipairs(tab) do      
	print(i, v)                 -- 1 one, 2 two
end 

-- 遍历顺序,比如table.nums,主要使用pairs
-- 也可能会使用:#, 但注意:table中不能包含nil
function table.nums(t)
    local count = 0
    for k, v in pairs(t) do
        count = count + 1
    end
    return count
end

pairs的实现:

— 每次循环调用iter,a为状态变量,table,i为控制变量
function iter(a, i) 
    -- i的值在闭包中进行了累计,闭包的本质就是用于数据的存储计算
    i = i + 1              
    local v = a[i]
    if v then 
        return i, v
    end 
end
function ipairs(a)
    return tier, a, 0
end   
  • Lua语言中可使用可变长参数,使用... 来表示,比如:
function Add(...)
    local args = {...} 		-- 获取可变参数table
    local result = 0
    for i, v in pairs(args) do
		result = result + v  
	end 
	return result 
end  
print(Add(1,2)) 		        -- 3
print(Add(1,2,3))			    -- 6
print(Add(1,2,3,4))			    -- 10
  • Lua语言中有个特性叫做尾调用

它被当作函数调用使用的跳转,当一个函数的最后一个动作是调用另一个函数而没有进行其他工作时,就形成了为调用。

进行尾调用的时不会产生额外的栈空间,我们将这种实现称为尾调用消除
不符合尾调用的方式有:

-- 该问题在于调用完g(x)后,f在返回前要丢弃g返回的结果
function f(x) g(x) end
-- 进行了加法
return g(x) + 1
-- 必须将返回值限制为1个
return x or g(x) 
return (g(x))

尾调用的方式为:

-- 方式1
function foo(n)
    if n > 0 then 
        return foo(n-1) end 
    end 
end 
-- 方式2,
return x[i].foo(x[j] + a*b, i + j)

只有返回形如 return func(args) 的才是尾调用

  • 为了更好控制局部变量的生效,可使用do ... end 方法
local a, b = 1, 2  		-- 在文件中生效
do 
    local a1, b1 = 3, 4 -- 仅在do ... end 程序块中生效
    print(a, b) 	    -- 1	2
    print(a1, b1)       -- 3 	4
end 
print(a, b)			    -- 1 	2
print(a1, b1) 			-- nil 	nil 
  • 尽可能的使用局部变量是一种良好的编程风格,它的优点:
  1. 避免不必要的的命名造成全局变量的混乱

  2. 避免同一程序中不同代码部分的命令冲突

  3. 会随作用域的结束而释放

  4. 访问局部变量比全局变量更快,因此编程中会将某些方法声明为局部,比如:

local RANDOM = math.random
local num = self:getNum()
  • 在连接字符串的时候,通常使用..

但是要注意下,关于读取较大文件内容时,会出现卡顿,比如:

-- 文件内容大小约为4.5M
local buff = ""
for line in io.lines() do 
    buff = buff .. line .. "\n"
end 

--[[
假设每行有20个字节,当读取2500行内容后,buff大小约为50KB,当程序在使用
buff .. line .. "\n"连接字符串的时候,会创建约50000个字节
然后再将50Kb的内容拷贝到新字符串中
如此重复的操作,对于不可变的字符串会产生至少移动50G的数据
]]

-- 可使用table.concat连接
local _tab = {}
for line in io.lines() do 
    -- 将内容放置到表中
    _tab[#_tab + 1] = line 
end 
local buff = table.concat(_tab, "\n")
  • 闭包是为保存状态提供的一种良好机制。

闭包就是一个可以访问自身环境中一个或多个局部变量的函数,这些变量upvalue将连续调用过程中的值保存在闭包中

ipairs的实现就是闭包。

function values(t)
    local i = 0
    return function()
        i = i + 1
        return t[i]
    end 
end 
  • 关于表的初始化
-- 初始化方式一:
local strTab = { x= "1", y = "2", z = "3"}
-- 初始化方式二:
local strTab = {}
strTab.x = "1"
strTab.y = "2"
-- 总结:方式一种能够提前判断表的大小,速度会更快
  • 判定表是否为nil或者{},可使用接口:next
local tabB = {}
if tabB and next(tabB) then  		-- 推荐,注意在Lua中,只有false,nil为假
	print("ok")
else 
	print("nil")
end 
  • 表删除元素的方式:
-- 不推荐
local tab = {2,3,2,3,2,3}
for _, value in pairs(tab) do 
	if value == 2 then 
		table.remove(tab, value)
	end 
end 
print(table.concat(tab, ","))			-- 2,2,3

-- 推荐方式1: 从后往前删除
local tab = {2,3,2,3,2,3}
for i = #tab, 1, -1 do 
	if tab[i] == 2 then 
		table.remove(tab, i)
	end 
end 
print(table.concat(tab, ","))		   -- 3,3,3

-- 推荐方式2: 使用while
local tab = {2,3,2,3,2,3}
local i = 1
while i <= #tab do 
	if tab[i] == 2 then 
		table.remove(tab, i)
	else 
		i = i +1
	end 
end 
print(table.concat(tab, ","))			-- 3,3,3
  • 元表主要用于对表进行操作,比如相加等
-- 创建新表时,默认不带元彪, 可使用:getmetatable
local _tab = {}
print(getmetatable(_tab)) 		    -- nil 

-- 设置元表,可使用:setmetatable
local _tab = {}
print(getmetatable(_tab)) 		    -- nil
local _tab1 = {}
setmetatable(_tab, _tab1)
print(getmetatable(_tab) == _tab1) 	-- true 

--[[
元表中有一些参数注意:
__index: 读取元表数据,如果普通表不存在,会根据__index继续查找字段或方法
__newIndex: 写入元表数据,元表存在时,会根据__newIndex写入数据
__metatable: 保护对象的元表metatable不被修改
__mode: 用于保证对象可以被回收,有key, value keyValue三种,尤其针对于table引用
]]
  • require的特性:
--[[
特性:
1. 加载文件
2. 避免重复加载文件
]]

-- 如果我想重复加载文件,实现方式:
package.loaded["app/LoginScene"] = nil 
require("app/LoginScene")

End

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹤九日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值