print("hello lua")
數據類型
數據類型 | 描述 |
---|---|
number | 數字,可當作double,5/2 == 2.5 |
integer | 整數,可當作int64,有整除符號,5//2 == 2 。lua 5.3 版本開始支持
|
string | 字符串 |
nil | 空值,變量未賦值前都是nil,給變量賦值nil相當于釋放變量 |
boolean | 布爾值,true和false |
table | 有兩種形態:1. hash表 2. 數組 |
function | 函數,數據類型一種,可以賦值給變量或作為參數 |
userdata | 自定義數據,用于擴展,lua vm負責內存管理 還有種light userdata,可以理解成 void * ,值類型,不需要內存管理 |
字符串定義
四種字符串定義方式
text1 = "最普通的字符串"
text2 = '和"一樣'
text3 = [[
長字符串定義,忽略任何轉義,最前面的換行,會被忽略
]]
text4 = [===[
長字符串定義,忽略任何轉義,加=號為了能在字符串里寫 a[b[1]],=數量不限
]===]
關鍵字
and break do else elseif end false for function if in
local nil not or repeat return then true until while
關鍵字不能用用作變量名。特別的:a.end = 1
出錯,但是可以用a["end"] = 1
注釋
-- 單行注釋
--[[
多行注釋,-和[之前不能有空格
]]
數字運算
-
+ - * /
基本的加減乘除,注意5/2 == 2.5
-
%
取余,a%b
=,可用于浮點數
1%-1.5 == -0.5
-
^
冪乘,a^i
=
字符串運算
-
..
字符串連接符,print("hello".." ".."world")
輸出hello world
邏輯運算
-
== ~=
相等比較,任意類型都可以,注意2 ~= "2"
-
> < >= <=
大小比較,不能數字字符串混用,2 > "3"
會報錯 -
not
非運算,not not a
相當于a ? true : false
-
and
與運算,a and b
相當于a ? b : a
,如果a為假值(nil
或者false
),返回a,否則返回b -
or
或運算,a or b
相當于a ? a : b
注意:
-
and
和or
的返回值不是bool類型的,而是參與運算的值的其中一個。 -
nil
和false
為假值,其他都是真值。也就是說,空串""
、數字0
和空表{}
都是真值。
變量
全局變量不需要聲明,任何時候a = 10
都是有效的,在a被賦值前,取a的值返回nil
。
局部變量聲明使用local
關鍵字,支持塊作用域,支持一次聲明多個。
local a,b = 1,2
if a then
local a,b = 10,20
print(a,b) -- 輸出10 20
end
print(a,b) -- 輸出1 2
補充:
局部變量性能好于全局變量,它的值在棧上,訪問時用的索引。
全局變量是取的全局表。print(1)
等同于_G["print"](1)
。
可以修改下變成
local print = print
print(1)
賦值語句
lua的=
表達式比較特殊,支持一次賦值多個,多余的忽略,不夠的補nil。
a, b = 1,2,3 -- 3忽略
c, d = 4 -- d是nil
交換x和y的值可以寫成x,y = y,x
,十分方便。
條件語句
三個基本結構。
if x then
print("if語句,如果x為真,輸出這句話")
end
if x then
print("if + else語句")
else
print("如果x為假,輸出這句話")
end
if x then
print("if + elseif語句")
elseif y then
print("x為假,y為真,才輸出這句話")
end
for循環
例子:
for i = 1,3 do
print(i)
end
輸出 1,2,3
可以指定步長
for i = 1,3,2 do
print(i)
end
輸出 1,3
補充:還有種for in
循環在table使用小節里介紹。
while循環
條件成立繼續循環,例子:
local i = 1
while i <= 3 do
print(i)
i = i+1
end
repeat循環(不常用)
條件成立退出循環,例子:
local i = 1
repeat
print(i)
i = i + 1
until i > 3
break語句
可以用break退出上述三種循環。
注意:
- break需要是代碼塊的最后一個語句。
- 沒有continue語句。
while true do
break --錯誤,后面還有代碼
local i
end
while true do
do break end -- 正確.do XXX end 是一個的代碼塊,break 確實放在了這段代碼的最后面
local i
end
table·數組
table的第一種形態:數組
1. 初始化
t = {1,2} -- 索引從數字1開始,相當于下面的例子
t = {};
t[1] = 1;
t[2] = 2;
2. 插入刪除
t = {1,2,3}
table.insert(t,4) -- 在結尾追加4,變成{1,2,3,4}
table.remove(t) -- 移除結尾元素,變成{1,2,3}
table.remove(t,2) -- 移除第2個元素,變成{1,3},會移動后邊的元素
3. 獲取長度
t = {1,2,3}
print(#t) -- 3
4. 遍歷
t = {1,2,3}
for i = 1,#t do
print(i .. " : " .. t[i]) -- 1:1 2:2 3:3
end
-- 這就是第二種for循環
for i,v in ipairs(t) do
print(i .. " : " .. v) -- 和上面一樣的功能
end
6. 排序
t = {1,3,2}
table.sort(t) -- 1,2,3
table.sort(t,function(a,b) return a > b end) -- 3,2,1
注意:
- table當成數組使用,數字索引從1開始
- table當成數組用時,要保證是緊湊數組,索引1..n,
t[i] ~= nil -- i in [1,n]
,后面會說明為什么。
table·hash表
table當成hash表使用
1. 初始化
t = {["x"] = 10, ["y"] = 20}
t = {x = 10, y = 20} -- 字符常量索引,和上面一樣
-- 多維數組
t = {
hp = 10,
pos = {100,200},
}
2. 刪除
t = {x = 1, y = 2}
t["x"] = nil -- 刪除key "x"
3. 遍歷
t = {x = 1, y = 2}
for k,v in pairs(t) do
print(k .. ":".. v) -- x:1 y:2
end
注意:
- table的key(索引)可以是除nil以外的任何值,
t[nil] = 1
報錯 - table的value(值)可以是任何值,特別的:
t['x'] = nil
的效果是刪除t['x']
的值 -
t["x"]
可以簡寫成t.x
,x不能是關鍵字,t.end = 1
報錯
table·不要數組和hash混用
table實際也可以混合數組和hash部分,如下
t = {
1,
["x"] = 2,
y = 3,
[4] = 4,
}
最好不要這么使用,數組和hash表是兩個不同的語義結構,lua的table實現混合了他們,可以統一理解成hash表。
table使用有坑
其中最大的坑獲取數組長度,lua提供了#
運算符。
但是:如果table的key不是1..n
,結果可能出錯,因為這個返回的是一個n,滿足t[n] ~= nil and t[n+1] == nil
。
t = {1,2}
t[3] = 1
print(#t) -- 數組是{1,2,3} 結果是 3
t[2] = nil
print(#t) -- 數組是{1,nil,3} 結果是1
如果是hash表,hash值作為索引,結果會更難預料。
所以說:table作為數組用,最好的緊湊數組
函數
兩種函數聲明形式
function func(a,b)
-- 先定義func變量,再定義函數,可以在這兒使用func遞歸調用
end
func = function(a,b)
-- 先定義了匿名函數,再賦值給變量func,這兒不能使用func遞歸調用
end
都是聲明一個名字叫func
,參數是a,b
的函數。
參數不需要說明類型,返回值不需要說明。
函數可以返回任何個數的數據,使用return
返回,return
和break
一樣,必須在代碼塊的最后面。
函數參數可以接受任意多個,使用...
來接受
function generate()
return 1,2,3
end
function MyPrint(...)
print("my print:",...)
end
MyPrint(generate()) -- my print: 1 2 3