一、基本知识
1.第一个程序:
print("hello lua");
在交互模式下直接运行:
> print("hello lua")
hello lua --输出
保存在文件中运行:
$ lua hello.lua
hello lua --输出
2.chunks:
* 定义:trunks指运行的语句块,一个文件,一个函数或是运行模式下每行语句、语句组合都是trunks;
* 语句之间的分割府(";")可有可无,为了可看性可维护性一般加“;”分割。
* 交互模式运行trunks:
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
>
a)交互模式键入的每行语句立即执行,不是完整的trunks时提示符为“>>”提示继续输入直至语句完整,交互模式可键入文件结束符(Ctrl-D in Unix, Ctrl-Z in DOS/Windows),或是调用OS库的os.exit()退出;
b)通过指定参数运行lua的一系列trunks,如一个文件a.lua有语句x = 1,文件b.lua有语句print(x),则在命令行调用>lua -la -lb 则输出“1”。此命令首先运行a,再运行b(-l命令会调用require),使用-i选项运行完trunks语句后进入交互模式;
c)使用dofile加载外部trunk。如:
文件:
ubuntu$ cat ext.lua
function ext_trunk()
print("external trunks")
end
运行:
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> dofile("ext.lua")
> ext_trunk()
external trunks
>
* 全局变量不需要声明,给出一个变量赋值后即创建变量。未初始化的全局变量值为nil,删除变量只需把值设置成nil:
print(b) --> nil
b = 10
print(b) --> 10
* 词法约定:
a)标识符:字母或者下划线开头的字母、下划线、数字序列(由于lua保留子也是下划线开头所以最好不要使用下划线开头标识符);
b)保留字(lua大小写敏感):
and break do else elseif end false for function if in local nil not or repeat return then true until while
c)lua注释:单行注释用“--”,多行注释用:--[[ --]];
* 命令行方式:lua [options] [script [args]]
a)-e :将命令直接传入(如:lua -e "print(math.sin(12))" --> -0.53657291800043);
b)-l:加载一个文件;
c)-i:进入交互模式;
d)通过_PROMPT内置变量存放交互模式的提示符
dht$lua -i -e "_PROMPT='mylua>'"
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
mylua>_PROMPT="hh>"
hh>
e)lua在运行参数之前会查找环境变量LUA_INIT的值,加载指定文件或代码(实验);
f)全局变量arg存放Lua命令行参数。
二、类型与值
1.lua有 八个基本类型:nil、boolean、number、string、userdata、function、thread和table。
a)可通过type函数获取变量或值的类型字符串。如:
print(type("Hello lua")) --> string
print(type(10.4*3)) --> number
print(type(print)) --> function
b)变量没有预定义类型,每个变量可设置成任意一种类型,函数也可以像变量一样使用.如:
print(type(a)) --> nil
a = 10
print(type(a)) --> number
a = "a string!!"
print(type(a)) --> string
a = print
print(type(a)) --> function
2. nil:特殊类型,只有一个值nil,全局变量赋值以前值为nil,删除一个全局变量只需把变量赋值为nil;
3. boolean:只有true和false两个值,在控制语句中除了false和nil为假,其余值都是真,如0和空串都是真;
4. number:表示实数,lua没有整数;
5. string:字符序列,lua为8位字节,字符串可以包含任何数值字符
a)string进行自动内存分配和释放;
b)lua支持的转义序列列表:
\a bell
\b back space -- 后退
\f form feed -- 换页
\n newline -- 换行
\r carriage return -- 回车
\t horizontal tab -- 制表
\v vertical tab
\\ backslash -- "\"
\" double quote -- 双引号
\' single quote -- 单引号
\[ left square bracket -- 左中括号
\] right square bracket -- 右中括号
c)字符串中还可以用\ddd表示字母,如:"alo\n123\""和'\97lo\10\04923"'是相同的
> print("alo\n123\"")
alo123"
> print('\97lo\10\04923"')
alo123"
>
d)用[[...]]表示字符串,可以包含多行,第一个字符是换行会被自动忽略。如:
> page = [[
>> <HTML>
>> <TITLE> An HTML Page</TITLE>
>> "this is a string'
>> </HTML>
>> ]]
> print(page)
<HTML>
<TITLE> An HTML Page</TITLE>
"this is a string'
</HTML>
>
e)lua会自动在string和numbers之间自动进行类型转换:
> print("10" + 1)
11
> print("10 + 1")
10 + 1
> print("-10" * "2")
-20
> print("hello" + 1) //出错hello不能转为数字
stdin:1: attempt to perform arithmetic on a string value
stack traceback:
stdin:1:
in main chunk
[C]: ?
> print(10 .. 20)
1020
> print(tostring(10) == "10")
true
> print(10 .. "" == "10")
true
> print(10 == "10") //虽然可以互相转换,但类型不同并不相等
false
>
6. function:函数也是一个类型,可以存储在变量中,可以作为函数参数,返回值。
7. userdata和thread后面介绍。
三、表达式
1. 算术运算符:
* 二元运算符:+ - * / ^(加减乘除幂)
* 一元运算符:- (减)
* 算术运算符操作数都是实数
2. 关系运算符:< > <= >= == ~=
* 俩值类型不同,lua认为两者不同,nil 只和自己相等:
> print(false == nil) --false和nil不相等
false
> print(x == nil)
true
>
* lua通过比较引用比较tables、userdata、functions:
> a = {}; a.x = 1; a.y = 0
> b = {}; b.x = 1; b.y = 0
> c = a
> print(a == c) --a和c互为引用
true
> print(a == b) --a和b的值完全相同,但是是不同对象
false
>
* lua比较数字按照传统数字大小,比较字符串按照字母顺序进行比较。混合比较数字和字符串会报错:
> print(2 < 15)
true
> print("2" < "15") --字符串比较字母顺序
false
> print("0" == 0) --类型不同
false
> print(2 < "15") --字符串和数字不能混合比较
stdin:1: attempt to compare number with string
stack traceback:
stdin:1: in main chunk
[C]: ?
>
3. 逻辑运算符:and or not
* 逻辑运算符认为nil和false为假,其余为真:
* and和or运算结果不是true或false:
a) a and b:如果a为false则返回a,否则返回b
> a = nil; b = 1
> print(a and b)
nil
> a = 1; b = 2
> print(a and b)
2
>
b) a or b:如果a为true返回a,否则返回b
> a = nil; b = 1
> print(a or b)
1
> a = 1; b = 2
> print(a or b)
1
>
c) and的优先级比or高
d) C语言中的a ? b : c 相当于nil中的(a and b) or c
* not只返回true或者false
> print(not nil)
true
> print(not false)
true
> print(not 0)
false
4. 连接运算符:..(两点),连接俩字符串,如果操作数为数字,则会转为字符串:
> print("hello " .. "lua")
hello lua
> print(0 .. 1)
01
>
5. 优先级(从高到低)
^
not - (unary)
* /
+ -
..
< > <= >= ~= ==
and
or
6. 表的构造:
* 最简单的构造函数:{} ,用来构造一个空表;
* 初始化一个数组(数组下标从1开始,数组元素可以是任何类型):
> arr = {"str", 10, math.sin(10)} --实际初始化的模型是这样的:arr = {[1] = "str", [2] = 10, [3] = math.sin(10)}
> print(arr[1]) --类型为字符串
str
> print(arr[2]) --类型为数字
10
> print(arr[3]) --类型为函数表达式
-0.54402111088937
* 初始化一个表:tbl = {x=1, y=2} 与 tbl = {}; tbl.x = 1; tbl.y = 2 和tbl = {['x'] = 1, ['y'] = 2}等价;
* 不管用何种方式建table,都可以向表中添加、删除任何类型的域,构造函数仅影响初始化
* 用table构造一个list:
words = {"A", "B", "C", "D"}
list = nil;
for k, v in pairs(words) do
list = {next=list, value=v}
end
l = list
while l do
print(l.value)
l = l.next
end
结果为:D B C A
* 混合使用列表和记录进行初始化:
polyline = {color="blue", {x=0, y=0}, {x=-10, y=0}}
print(polyline[2].x) --> -10
结果为:-10
* table下标一般不从0开始,很多标准库不支持。构造函数中的域可以用逗号(,)隔开,也可以用分号(;)隔开
四、基本语法
Lua 传统语句:赋值语句、控制结构语句、函数调用等,同时也支持非传统的多变量赋值、局部变量声明。
1. 赋值语句
* a = "hello " .. "lua" --单个变量赋值
* a, b = 10, 20 ---两个变量赋值相当于 b = 20; a = 10(先右边赋值再左边赋值)
* x, y = y, x --根据先右边赋值再左边赋值的特性,此代码可以交换两个变量
* 当变量个数>值个数时多余变量值为nil:
a, b = 10; print(a,b); -- 结果为10 nil
* 变量个数<值个数时多余的值被忽略
a, b = 10, 20, 30; print(a,b); ---结果为10 20
* 注意:两个变量赋值按照先右后左,但是多个变量的情况下必须从左到右依次赋值,函数返回不管多少个值都是从左到右依次赋值。
2. 局部变量与代码块
* 局部变量添加local来声明,局部变量只在声明局部变量的代码块内有效
* 在交互模式下局部变量的作用域可能和想的会有所不同,因为一行执行是个完整的chunk
> local i = 1
> print(i)
nil
>
* 利用do ... end可以更好的定义语句块,为一个chunk划分界限。do ... end相当于C中的{...}
> do
>> local i = 1
>> print(i)
>> end
1
>
3. 控制结构语句
*if语句的三种形式:
if conditions then ---1
then-part
end;
if conditions then ---2
then-part
else
else-part
end;
if conditions then ---3
then-part
elseif conditions then
elseif-part
.. --->多个 elseif
else
else-part
end;
*while 语句
while condition do
statements;
end;
*repeat-until语句
repeat
statements;
until conditions;
*for语句的两种
a) 数值for循环
for var=exp1,exp2,exp3 do loop-part end
b) 范型 for循环
for i,v in ipairs(a) do print(v) end
4. break和return语句
* break语句用于退出循环:for repeat while --循环外不可使用
* return 用来返回函数结果
* break和return只能在block的前一句,即在end,else,until之前
* 通常可以在代码中插入 do return end的方式使得return可以出现在代码块中间。