Lua語言的數據類型很是豐富,包括nil、boolean、number、string、userdata、function、thread 和 table等類型。Lua中全部的數據類型的默認值都是nil。html
只有一個值,就是nil自己。數組
跟其餘語言同樣,包括false和true倆個值。 在lua語言中,只有nil和false的值爲「假」,其餘的都是「真」bash
number類型表示雙精度浮點數字,lua中沒有整數類型,全部的數字類型都是number,這個跟js實際上是同樣的。 咱們能夠省略小數部分和指數部分,下面這些都是有效的number類型。數據結構
4 0.4 4.57e-3 0.3e12 5e+20
複製代碼
首先String在lua中是不可能的值,這個跟大多數語言中的string類型設計是同樣的,好比Java和JavaScript,Go等等(C語言的string是可變的)。 因此,若是在lua中你須要修改一個字符串,你能夠像下面這樣,從新生成一個新的字符串。函數
a = "one string"
b = string.gsub(a, "one", 'another') -- 講one替換爲another
print(a) --> one string
print(b) --> another string
複製代碼
注意看上面的代碼,單引號和雙引號均可以表示一個字符串。這點跟js也同樣。ui
在lua中,lua會自動管理字符串的內存釋放和回收,因此不用擔憂內存問題。編碼
在lua中,字符串裏面能夠包含轉義字符,和js不一樣的是,lua中可使用轉義的數字來表示ASCII編碼。舉個例子:lua
"alo\n123\""
'\97lo\10\04923"'
複製代碼
上面這兩個字符串是相等的,由於a的ASCII碼是97,換行符\n的ASCII碼是10,數字1的ASCII碼是49。因此上面的兩個字符串是徹底同樣的。spa
lua中若是想表示多行字符串,可使用[[...]],而且能夠嵌套。可是這種字符串表示,不會去解析轉義字符。線程
[[ <div> <span>hello</span> <p> .... </p> </div> ]]
複製代碼
lua中對於字符串的任何數字操做,都會嘗試將字符串轉換爲數字類型。
print("10" + 1) --> 11
print("10 + 1") --> 10 + 1
print("-5.3e-10"*"2") --> -1.06e-09
print("hello" + 1) -- 錯誤:stdin:1: attempt to perform arithmetic on a string value
print(1 + "hello") -- 錯誤:stdin:1: attempt to perform arithmetic on a string value
複製代碼
這裏跟js裏面仍是有區別的,js裏面,第一個會輸出「101」,第四個會輸出「hello1」,第五個會輸出「1hello」。
與上面相反,lua中對於數字的任何字符串操做,都會講數字轉換爲字符串。
print(1 .. 3) --> 13
複製代碼
這裏的..是lua中的字符串相加的操做。注意..前的空格,不然會被當作是前一個數字的小數點。後面的空格沒有關係。
對於上面,你會以爲lua中的字符串和數字會自動轉換,那比較的時候,是否也會自動轉換呢?答案是不會轉換。
print(1 == "1") --> false
複製代碼
咱們知道在js裏面若是使用1=='1'來判斷是否相等,會返回true,必須使用===來使用強相等的判斷,這點lua中不須要。lua中會直接判斷類型是否相同, 若是不一樣直接返回false。\
若是須要字符串和數字比較,那就須要先將字符串轉換爲數字或者將數字轉換爲字符串:
print(1 == tonumber('1')) --> true
print(tostring(1) == '1') --> true
複製代碼
tonumber和tostring不用說你也知道是幹嗎的。 官方文檔:www.lua.org/pil/2.4.htm…
lua中的table類型有點相似js中的對象,可是比js中的對象更增強大。它能夠表示數組,set,隊列等各類數據結構。lua中的table是引用類型,這意味着不會存在數據複製和拷貝的問題。操做table就是在操做指針,背後也沒有副本或者新table的建立。
a = {} --> 聲明一個table
複製代碼
而後能夠給這個table各類操做:
a[1] = "1"
a["k"] = "v"
複製代碼
基本上你在js裏面怎麼使用對象,這裏就能夠怎麼使用lua的table,是否是很簡單?
再來看個例子:
const a = {};
a['1'] = 1;
a[1] = 2;
console.log(a[1]) // 2
console.log(a['1']) // 2
複製代碼
a = {}
a['1'] = 1
a[1] = 2
print(a[1]) --> 2
print(a['1']) --> 1
複製代碼
注意上面這一個區別,js中是會將key轉換爲字符串的。而在lua中,是不會的。
除了上面這種a[1]形式訪問table中的屬性外,還能夠經過a.x,a.y的形式訪問,可是注意,x,y不能是數字。因此上面的a[1]和a['1']都不能使用這種形式。
注意: a.x和a.y這種形式,是經過x,y的值去訪問table中的屬性,而a[x]和a[y]是經過x,y自己做爲索引去訪問table,這裏是有區別的:
x = 10
a = {}
a[x] = 1
a.x = 2
print(a[x]) --> 1,這裏的key是10
print(a.x) --> 2,這裏的key是「x」
複製代碼
這個跟js裏面是同樣的。
a = {}
a[0] = 'one'
a[1] = 'two'
a[2] = 'three'
for i,line in ipairs(a) do
print(i .. '-->' .. line)
end
複製代碼
上面的代碼輸出以下:
1-->two
2-->three
複製代碼
爲何0不見了呢?由於在lua語言中,索引是從1開始的,這是一個約定,全部內建的函數和功能都是這個約定。 上面的代碼你能夠經過a[0]來顯示訪問到這個值。不過建議不要這麼作。
function類型是lua中的一等公民。嗯,js裏面是否是也是這樣?
function add (a)
local sum = 0
for i,v in ipairs(a) do
sum = sum + v
end
return sum
end
複製代碼
a={}
a[1]=1
a[2]=2
add(a) --> 3
複製代碼
這種類型是專門用來在lua中表示由C語言建立的各類數據類型的。這裏就先不看, 由於不多須要用到這個。
在lua中,有一個coroutine(協程)的概念,他跟線程有點相似,lua中的協程有本身的局部變量,可是共享全部的全局變量。在同一時間只會執行一個協程,這點跟線程是不同的,線程是同一時間會執行多個線程。
co = coroutine.create(function ()
print("hi")
end)
print(co) --> thread: 0x8071d98
print(type(co)) --> thread
複製代碼
在coroutine中,有一個create函數。經過這個函數能夠建立出一個thread類型變量,注意這裏表示建立了一個協程。
lua中的協程有3種狀態,suspended,running,dead。 剛剛建立的協程的初始化狀態是suspended,也就是說協程不會自動的運行,能夠經過下面的代碼查看協程的狀態。
print(coroutine.status(co)) --> suspended
複製代碼
使用如下代碼來啓動一個協程:
coroutine.resume(co) --> hi
print(coroutine.status(co)) --> dead
複製代碼
在js中咱們知道,有一個關鍵字yield,用來暫停生成器函數的執行。舉個例子,
function *test(){
yield 1
yield 2
return 3
}
const testGe = test();
testGe.next() // {done: false, value: 1}
testGe.next() // {done:false, value: 2}
複製代碼
生成器函數test被調用的時候回返回一個生成器。這個生成器每次調用next的時候 就會執行函數的代碼,直到遇到yield關鍵字就暫停執行。
相似的,在lua中也有yield,咱們來看個例子:
co = coroutine.create(function ()
for i=1,10 do
print("co", i)
coroutine.yield()
end
end)
複製代碼
看上面的代碼,當咱們執行coroutine.resume(co)的時候,都會執行協程中的代碼,可是當遇到coroutine.yield()的時候灰停在協程的執行。
運行一次的輸出結果:
coroutine.resume(co) --> co 1
print(coroutine.status(co)) --> suspended
複製代碼
運行第二次:
coroutine.resume(co) --> co 2
print(coroutine.status(co)) --> suspended
複製代碼
發現沒有,這裏和js中的生成器函數那貨是否是很是的相似? 確定的,你運行10次以後,再去查看co的狀態,確定是dead狀態了。你本身去試試吧。
使用了yield的協程函數內部,怎麼傳遞參數呢?看下面的例子:
co = coroutine.create(function (p)
for i=1,10 do
coroutine.yield(p + i)
end
end)
複製代碼
在上面的例子中,咱們給協程函數添加了一個參數p,而且在調用coroutine.yield的時候,執行p+i的表達式,這個表達式執行的結果,就是該次執行協程的返回結果。
咱們來看下: 第一次運行:
print(coroutine.resume(co, 1)) --> 2
複製代碼
第二次運行:
print(coroutine.resume(co, 1)) --> 3
複製代碼
看到這裏你應該明白了,每次執行resume的時候,都是執行到yield位置暫停,而後執行yield中的表達式,而後將結果返回。 官方文檔: www.lua.org/pil/9.html
原文地址:codebe.org