【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

相关文章
相关标签/搜索