Lua学习笔记(1)-基础知识、表达式语法


Lua的特点概括:

  • 轻量级动态语言,解释型语言
  • 脚本语言,适合写游戏逻辑。脚本语言运行于虚拟机之上,虚拟机运行在游戏逻辑上。
  • 开源语言。官网:http://www.lua.org/download.html
  • Lua由C语言编写而成,像一个工具包,可扩展性强

Lua概念介绍网站:

https://my.oschina.net/xlplbo/blog/312837

Lua入门教程网:

http://www.runoob.com/lua/lua-tutorial.html


开始学习《Lua程序设计第二版》:

执行一个Lua文件:
我尝试以下几个命令:

% lua hello.lua 

$ lua hello.lua

dofile("E:/project/myStudy/LuaStudyNew/test_2.lua") --加载并执行一个Lua文件

但是我用LuaForWindows_v5.1.4-46.exe安装的Lua解释器只有第三个命令方式OK

需要注意:用SciTE小IDE新建的lua文件保存后不带文件后缀,dofile()传路径时不带.lua,如果新建一个带.lua出文本 则dofile()里的路径需带.lua后缀


Lua基础概念:

程序块(chunk):

Lua每次执行的代码段,如源代码文件或交互模式中输一行代码。Lua中不要求语句结束符“;”,可输入也可以不输入

a=1-- 语句结束可输入";"也可不输;
b=a*2

a=2;b=3;

a=3 b=4 --注:一行连写了两句话虽然丑陋,但这么写却是OK的
print("a="..a,"b="..b)


--function study
function norm(x,y)
    return (x^2+y^2)^0.5
end

function twice(x)
    return 2*x
end

终端依次输入以下三个命令的demo则为加载1chunk_demo.lua文件,并使用源文件中的函数。其中dofile(“”)函数既加载了程序库也立即执行了里面的内容

> dofile("e:/project/mystudy/luastudynew/chunkdemo_1.lua")
'a=3'
'b=4'
> x=norm(1.1,3.2)
> print("result x="..x,"result twice(2)="..twice(2))
'result x=3.3837848631377'
'result twice(2)=4'

命名规范

标识符命名由字母、数字、下划线构成,但不能以数字开头

注意:

  • 命名避免下划线+全大写 格式,这类标识符可视作有特殊用途的对象,如_VERSION
  • 小写中的所有Lua关键字:
and break do else elseif end
false for function if in local nil
not or repeat return
then true until while 
  • Lua大小写敏感
  • 注释方法
--是行注释


段注释
--[[ 
我被注释了 
--]]   

取消注释的方法,相当于把"-[[ "变成了一个普通注释,末尾的"--]] "也成了空注释
---[[ 
我被注释了 
--]] 

全局变量

Lua中全局变量不需要声明,只需要将值赋值给一个全局变量就可以创建了。

注意:我安装使用的Lua版本是5.1,用软件自带的解释器print(b)如果b未赋值的会报警告,而在cmd 下lua -e “print(b)” 却不会报错,b默认值为nil

>print(b)

variable ‘num’ is not declared

但是在《Lua程序设计第二版》的pdf中却说打印一个未定义的变量不会报错,变量的默认值是”nil”,具体修正为本Lua的变量是否有默认值应该取决于所使用的解释器吧

解释器程序(the dtand-slone interpreter)

可以通过解释器小程序来直接使用Lua

如果源代码文件行首有以下内容:

#!/user/local/bin/lua

或者

#!/user/bin/env lua

则可直接可以调用脚本文件,不用显式的调用Lua解释器

解释器用法格式:

lua [选项参数] [脚本[参数]]

几个选项参数:
1. 选项参数”-e”:
-e 后面可直接跟代码串,只要安装了Lua,在cmd下执行以下命令,即可打印print()中内容

lua -e “print(math.sin(12))”

  1. 选项参数”-l”,小写L:
    用来加载库文件,后面跟库文件名
    以下命令是先加载库文件a,再执行”x=10”,”-i”参数指定了最后进入交互模式

lua -i -l a -e “x=10”

小贴士1:”_RPOMPT”全局变量关键字表明了Lua交互模式的命令提示符

lua -i -e”_PROMPT=’lua>’”

==效果具体见”临时图片”里的”lua改命令行提示截图”==

小贴士2::交互模式下打印表达式除了用”print()”,还可以直接”=表达式”这么写

==具体见图“用等号打印表达式”==

小贴士3:解释器在运行脚本前会用所有的命令行参数创建一个名为”arg”的table,脚本名称位于索引0上。其第一个参数的索引为1

如下命令

lua -e “sin=math.sin” script a b

解释器存到arg的内容如下,因为通常脚本参数只会用正索引

arg[-3] = “lua”

arg[-2] = “-e”

arg[-1] = “sin=math.sin”

arg[-0] = “script”

arg[1] = “a”

arg[2] = “b”
3.


Lua的值与类型

由于Lua是动态语言,该语言没有定义类型的语法,因此每个值都“携带”了它自身的类型信息

Lua中的8种基础类型:

类型名 定义
nil 空,类似于C#的null
boolean 布尔类型
number 数字,指所有实数,Lua没有整数类型,但用来计算任何32整数时也不会产生四舍五入的错误
string 字符串
userdata 自定义类型
function 函数
thread 线程
table

==注意: Lua中变量没有与定义类型,任何变量都可以包含任意类型的值==

print(type(a)) --[[type()函数获取一个对象的类型,返回一个字符串,
左侧结果:可能nil也可能报“variable 'a' is not declared”的警告--]]

a=10
print(type(a)) --输出number
a="string...."
print(type(a)) --输出string
a=print        --把函数赋给变量也是OK的!!
print(type(a)) --输出function
  • Lua中为假的条件:false和nil,其他情况下都为true.则意味着数字0和空字符串在Lua中也未为true
  • 补充单双精度的基础知识点:单精度,一般占四个字节32位,精确到小数点后六位。
    双精度,占八个字节64位,精确到小数点后15位
    具体在Lua中,书中表示双精度浮点数表示整数时就不会出现“四舍五入”的bug,而单精度则会。查了一圈资料也没完全明白。大致意思是,表示较大整数时浮点数放不下,因为整数本来一般占四个字节,有效数值31位,如int.max=2147483647,单精度浮点数肯定是放不下了,它还得有小数位呢。

==Lua中的操作符==

“..”字符串连接符,用法:

a=123
print("a is"..a)

“#”前置操作符,获得字符串的长度,用法

a="1212"
print(#a) --输出为4

==table类型:==

具体来说,table 其实是个类,其内容不是值也不是变量,而是一个对象。也是Lua中的主要数据结构
table的用法:

a={}  --创建一个table对象a

k = "x"
a[k] = 10 --table赋值
a[20]="great"

print(a[k]) --输出为10

a["x"] =a["x"]+1
print(a["x"])  --输出为11,a["x"]指向a[k]

书中说对元素k的访问方法除了a[k]这么写,还可以直接a.k来用,如打印print(a.k),不过我在5.1试过了,不OK,print(a.k)出来是空值,跟书中所述的值为nil也不一致。所以。。能用基本用法就已经很艰辛了。

如下demo为填充一个table a:

a={}
for i=1,10 do
   a[i] = io.read()  --接收十行塞进a,此时a相当于一个数组
end

遍历打印a所有元素:

for i=1,#a do
  print(a[i])
end

访问指定索引的元素,如访问第一个

print(a[1])

所引用法,#a特殊用法,用来表示table a的最后一个索引:

> a={"2","dsfa","fgdsgdf"}
> print(a)      
{'2','dsfa','fgdsgdf'}

> print(a[#a])   --输出最后一个元素,'fgdsgdf'
> a[#a]=nil      --删除最后一个元素
> print(a)       
{'2','dsfa'}

> a[#a+1]="zzzz" --末尾插入一个新元素
> print(a) 
{'2','dsfa','zzzz'}

数组空间问题:

a={}
a[1000]=1

print(a)  --打印数组的结果将会是空

print(table.maxn(a)) --或print(table.getn(a)),打印数组长度的时候,输出为1000.
--因此,这两句话相当于开辟了一个空间为1000的空表。

注意的是

  • 未初始化的table元素值为nil
  • ==table使用索引访问的时候,第一个索引的下标为1而非0!即a[1]才是第一个元素==
  • table a 使用a[key为整数] 赋值访问的时候,相当于一直在操作一个数组。因此a[10],a[“+10”],a[“10”]指向不同的三个元素!所以,在对复杂表访问的时候,key类型不确定的话很可能惹来一些坑。保险做法是指定key的类型,如下demo,最后两行指定访问a[10],而不是a[“10”]或a[“+10”]
i=10;
j="10";
k="+10";
a={}
a[i]= "first string";
a[j] = "second string"
a[k] = "third string"

print("i value ="..a[i])
print("j value ="..a[j])
print("k value ="..a[k])

--use type number index
print("j as number,value ="..a[tonumber(j)]) --输出"first string"
print(tonumber(k))
print("k as number,value ="..a[tonumber(k)]) --输出"first string"

==function,函数类型:==

由于在Lua中,由于function是作为“普通类型”出现的,即函数有几个特别用处:
1. 可以将函数赋给一个变量
2. 将函数作为一个参数传给别的函数使用
3. 一个函数作为另一个函数的返回值


==usertdata自定义类型和 thread线程:==

userdata类型可以任意C语言数据存储到Lua变量中。

这部分主要记录Lua表达式的用法

特点:Lua表达式除了一般语言的表达式用法外,还可以包括函数定义和table构造


表达式运算符

除一般运算符+,-,*,/,^(指数),-(负号)外。lua对于%取模的定义:

a%b == a - floor(a/b)*b

对于来说以上计算是有意义的。而对于小鼠来说,还可以有别的用法,比如截取小数位等,以下demo是限制一个浮点数的小数位:

x = math.pi;

print(x)

print(x%1) --打印出小数位

print("limit demical 2 =", x-x%0.01) --限制保留两位小数点,输出3.14

关系操作符

Lua中定义的关系操作符:<, >, <=, >=, ==, ~=(表示不等于),关系操作符的运算结果都是true/false

注意:
- 用来比较运算的时候,不同类型的值,结果一定false,同时nil只跟自身相等
- 对于值类型,可以直接内容是否相等,但对于table,userdata和function, 只有引用相等时”==”结果才为true
- 比大小”<”,”>”运算符由于只有在数字和数字、字符串和字符串比较的时候才有意义,因此,如果执行print(2<”12”) 这样的比较时,Lua将会抛出一个异常:

attempt to compare number with string


逻辑操作符

逻辑操作符有:and, or, not,逻辑操作将false和nil视为假,其他任何东西视为真。

因此,对于and操作,如果第一个操作数为假,就返回第一个操作数,否则返回第二个操作数

对于or操作符,如果第一个操作数为真,就返回第一个操作数,否则返回第二个操作数

以下是比较的小demo:

> print(a and 5)
5
> print(false and 13)
false
> print(4 or 5)
4
> print(false or 5)
5
> print(nil and 12)
> --注,输出其实应该是nil,只不过没打印显示出来

Lua中判空赋值操作:

> v=12
> m= m or v --注意,这个小用法可以相当于在检查m未定义的时候给一个值v
> print(v)
12
> print(m)

Lua中实现三目运算符a?b:c的用法,使用(a and b) or c 结构去实现:

> x=1;y=4
> max= (x>y) and x or y --实现获取x,y中的较大值,
> print("max="..max)
'max=4'

not 关键字,”not a” 相当于i“是否a为false?”的意思,结果返回true/false

print(not nil) --输出true
print(not false) --输出true
print(not 0) --输出false
print(not "123") --输出false

字符串连接

“..” 操作符用来连接两个字符串,用法如下:

print("hello ".."world") --输出hello world

注意:Lua中的字符串是不可变的值,连接操作符会创建一个新字符串,不会影响原变量。


运算优先级

Lua中操作符优先级从高到低
^
not # -
    / %
    -
..
< > <= >= ~= ==
and
or

table构造式(table constructor)

以下是三种table的构造表达式,需要注意的是,a3构造看上去很优雅,x,y默认类型为字符串,访问的时候也是a3[‘x’]这样来取值的


--构造table一些方法
a1={}
a2={"Sunday","Monday","Tuesday"}
a3={x=1,y=20}


print("\n\n a1=",a1)
print("a2=",a2)
print("a3=",a3)  --输出{y=20,x=1}
print(",a3[x]=") 
print(a3['x'])   --输出1

a3.z= 1000  --给a3添加一个z元素值为1000

使用table构造一个链表如下demo,其中链表的每个节点都是一个table,table中包含两个字段:value(每行的内容)和next(指向下一个节点的引用)

--get 10 lines input to create a linklist,
list=nil
for i=1,10 do
 line = io.read()
 list={next=list, value=line;}
end


--print linklist
local l =list
while l do
   print(l.value)
   l= l.next;
end

此外,关于之前发现的Lua下标索引是从1开始这个问题,Lua虽然提供了修改元素起始索引的方法,,但从下表现来看,“似乎”仅仅是修改了索引访问而已,甚至于获取table属性getn(),max()的值都被影响到了,所以还是别挣扎修改索引了,乖乖用 a={“aaa”,”bbb”,”ccc”} 构造吧

> a={[0]="aaa","bbb","ccc"}
> print(a)
{'bbb','ccc'}
> print(a[0])
'aaa'
> print(table.getn(a))
2
> print(table.maxn(a))
2

补充构造表语句分隔符除了”,”还可以使用”;”,如a={“aaa”;”bbb”,”ccc”}这样写也是OK的

你可能感兴趣的:(Lua,StudyNote)