【Lua學習筆記2】Lua中的基本數據類型介紹

數據類型

Lua語言的數據類型很是豐富,包括nil、boolean、number、string、userdata、function、thread 和 table等類型。Lua中全部的數據類型的默認值都是nil。html

nil

只有一個值,就是nil自己。數組

boolean類型

跟其餘語言同樣,包括false和true倆個值。 在lua語言中,只有nil和false的值爲「假」,其餘的都是「真」bash

number類型

number類型表示雙精度浮點數字,lua中沒有整數類型,全部的數字類型都是number,這個跟js實際上是同樣的。 咱們能夠省略小數部分和指數部分,下面這些都是有效的number類型。數據結構

4     0.4     4.57e-3     0.3e12     5e+20
複製代碼

string類型

首先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…

Table類型

lua中的table類型有點相似js中的對象,可是比js中的對象更增強大。它能夠表示數組,set,隊列等各類數據結構。lua中的table是引用類型,這意味着不會存在數據複製和拷貝的問題。操做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裏面是同樣的。

遍歷table

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類型

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
複製代碼

官方文檔:www.lua.org/pil/2.5.htm…

userdata類型

這種類型是專門用來在lua中表示由C語言建立的各類數據類型的。這裏就先不看, 由於不多須要用到這個。

thread類型

在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

www.lua.org/pil/9.1.htm…

原文地址:codebe.org

相關文章
相關標籤/搜索