第二课 类型和值

Lua是一种动态类型语言。没有类型定义的语法。每个值都携带了它自身的类型信息。
8种基础类型:nil(空) boolean(布尔) number(数字)
string(字符串) userdata(自定义类型) function(函数)
thread(线程) table(表)
函数type可 根据一个值返回其类型名称。
print(type("hello world")) -->string
print(type(type)) -->function
print(type(nil)) -->nil

变量没有预定义类型,任何变量都可以包含任何类型的值

a = print
a(type(a)) -->function
在Lua中,函数是作为“第一类值(first-class value)”来看待的,可以像操作其他值一样来操作函数值

nil(空)
nil是一个类型,它只有一个值nil。它的主要功能是用于区别其他任何值。

boolean(布尔)
true,false。Lua将nil和false视作“假”,其他情况均为“真”

number(数字)
number类型用于表示实数。Lua没有整数类型,因为没有必要。事实上,只要使用双精度来表示一个整数,就不会出现“四舍五入(Rounding)”的错误。

string(字符串)
Lua完全采用8位编码,Lua字符串中的字符可以具有任何数值编码,包括数值0。
Lua中的字符串是不可变的值。所以没有字符串变量一说。要改变字符串值只能创建一个新字符串。
字面字符串(literal string)需要以一对匹配的单引号或双引号来界定:
a = "a line"
b = 'another line'
Lua字符串中可以有类C语言中的转义序列。如:\n,\r等。
可以通过数值来指定字符串中的字符,数值以转义序列“\<ddd>”给出,<ddd>是一个至多3个十进制数字组成的序列。
“alo\n123\"” == '\97lo\10\04923"'
ASCII 编码中,'a'是97,换行是10,‘1’是49。
一对匹配的[[]]双括号来界定一个字母字符串,就像写块注释一样。Lua不会解释其中的转义序列。如果字符串的第一个字符是换行字符,Lua会忽略它。
page = [[
<html>
<head>
<title>An Html Page</title>
</head>
</html>
]]
[[之中还可以加任意数量的==,两边许匹配==数量
[===[ ]===]
--[==[ --]==]
Lua提供了运行时的数字和字符串的自动转换。
print("10" + 1 ) -->11
print("hello" + 1) --错误
同样,在Lua期望一个字符串但却得到一个数字时,它也会将 数字转换成字符串。
print(10 .. 20) -->1020
..(两个点)是字符串连接符,当直接在一个数字后面输入它时,必须使用一个空格来分割它们。不然,Lua会将第一个点理解为一个小数点。
比较运算符10=="10"总为false。
如果需要显示地将字符串转换为数字,可以使用函数tonumber。如果字符串的内容不能表示一个正确的数字时,tonumber将返回nil。
若要将-个数字转换成字符串,可以调用函数tostring,或者将该数字与一个空字符串连接。
print(tostring(10) == "10") -->true
print(10 .. "" == "10") -->true
在Lua5.1中,可以在字符串前放置操作符“#”来获得该字符串的长度。#号被称作“长度操作符”
a = "hello"
print(#a) -->5

table(表)
table类型实现了“关联数组”。关联数组是一种具有特殊索引方式的数组。不仅仅可以通过整数来索引它,还可以使用字符串或者其他类型的值(除了nil)来索引它。table没有固定的大小,可以动态地添加任意数量的元素到一个table中。Lua也是通过table来表示模块(module)、包(package)和对象(object)的。当输入io.read的时候,其含义是“io”模块中的read函数。对于Lua而言,这表示“使用字符串“read”作为key(键)来索引table io”
table既不是“值”也不是“变量”,而是“对象”。
table的创建是通过“构造表达式”完成的,最简单的构造表达式是{}。
a = {} --创建一个table,并将它的引用存储到a
k = "x"
a[k] = 10 --新条目,key="x",value=10
a[20] = "great" --新条目,key=20,value="great"
print(a["x"]) -->10
k = 20
print(a[k]) --> "great"
a["x"] = a["x"] + 1 --递增条目"x"
print(a["x"]) -->11
table永远是匿名的,一个持有table的变量与table自身之间没有固定的关联性。
a = {}
a["x"] = 10或者a.x = 10
b = a --b与a引用了同一个table
print(b["x"])或者print(b.x) -->10
b["x"] = 20
print(a["x"]) -->20
a = nil --现在只有b还在引用table
b = nil --再也没用对table的引用了

Lua中的数组表示:
a = {}
for i = 1,10 do
a[i] = io.read()
end
就Lua的习惯而言,数组通常以1作为索引的初始值。并且有不少机制依赖于这个惯例。
在Lua5.1中,长度操作符“#”用于返回一个数组或线性表的最后一个索引值(或为其大小)。
--打印所有的行
for i =1,#a do
print(a[i])
end
print(a[#a]) --打印列表a的最后一个值
a[#a] = nil --删除最后一个值
a[#a + 1] = v --将v添加到列表末尾

数组大小的概念是模糊的,因为数组实际上是table。
对于所有未初始化的元素的索引结果都是nil。Lua将nil作为界定数组结尾的标志。当一个数组有空隙时,即中间存在nil时,长度操作符会认为这些nil元素就是结尾标记,因此应该避免对那些含有空隙的数组使用长度操作符#。如果真的需要处理那些含有“空隙”的数组,可以使用函数table.maxn(Lua5.1新函数),它将返回一个table的最大正索引数。
a = {}
a[10000] = 10
print(table.maxn(a)) -->10000
i = 10;j = "10"; k = "+10"
a = {}
a[i] = "one value"
a[j] = "another value"
a[k] = "yet another value"
print(a.j) -->"another value"
print(a.k) -->"yet another value"
print(a[tonumber(j)]) -->"one value"
print(a[tonumber(k)]) -->"one value"

function(函数)
函数是作为“第一类值”来看待的。就和其他普通类型一样。可以存储在变量中,可以作为函数参数传递,可以作为函数返回值返回。

userdata(自定义类型)和thread(线程)
由于userdata类型可以将任意的C语言数据存储到Lua变量中。在Lua中,这种类型没有太多的预定义操作,只能进行赋值和相等性测试。










































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章