Lua学习(一)基础语法
文章目录
- 一、Lua介绍
- 二、基础语法以及使用的细节
- 三、学习总结
前言
因为Lua技术能够很好的支持游戏热更新,因此在游戏开发过程中使用广泛。这里参考电子工业出版社出版的由Robertp Ierusalimschy(巴西)编写,周惟迪先生翻译的Lua程序设计(第二版)进行自主学习。
一、Lua是什么?来认识一下
(1)Lua语言设计初衷
Lua语言起初是想设计成能与C语言或者其他常用语言编写的软件相互集成。Lua作为一门简单小巧的语言,一部分原因是因为不准备做C语言已经做的很好的方面(例:C语言超高的性能、底层操作能力以及与第三方软件之间的接口)。Lua提供的相对于硬件高层抽象、动态结构、无冗余(No Redundancy)、建议的测试和调试这些特性是C语言不擅长的。Lua还实现了一个安全的运行环境、一套自动内存管理机制、优秀的字符串处理能力和动态大小数据的处理功能。
(2)Lua语言的可扩展性
Lua语言中大部分基础功能是通过外部库进行实现的。其中的许多特性体现出他的可扩展性:
1、动态类型:为多态提供了支持
2、自动内存管理:简化了接口,从而无需决定谁分配内存、谁释放内存以及如何处理溢出等。
3、高阶(Higher-order)函数和匿名函数:允许实现更高层的参数化,能使函数变得更加通用。
(3)Lua语言的特点
Lua语言也是一门“胶水语言”。支持基于组件的软件开发方法。不仅可以用于黏合组件还可以用于适配组件或者改造组件,甚至创建出一个全新的组件。
简易性:Lua是一种简单、小巧的语言。完整的Lua发布版可以很轻松的存放在一张软盘中。
高效:独立测评结果显示Lua是脚本(解释型的)语言领域中最快的语言之一。
可移植性:Lua不仅可以同时运行在Windows和UNIX平台上,可以运行在任何平台上。Lua不使用条件编译对不同平台进行特殊处理,只依赖于ANSI(ISO)C标准来编写Lua的实现代码。
注:关于编译型语言与解释型语言认识与区分
编译型语言(通篇翻译>>生成翻译后文件>>执行翻译后文件):C C++
优点:执行效率快
不足:移植性差(不跨平台)
解释型语言(翻译一行执行一行,不生成解释性文件):Lua Javascript php python
优点:跨平台
不足:执行效率稍微慢(由于硬件现在不断进步,所以不是很明显)
其中Java不属于上述两种(oak语言):
java有一个jvm虚拟机,.java文件通过javac先编译成.class文件,再通过java虚拟机jvm解释执行(跨平台性)
二、:Lua基础语法与使用的细节问题
在学习Lua语言时用到的编译器是SublimeText,因为它简洁,执行起来比较快。缺点是只有少部分提示,考验代码编写时的基础语法英文。SublimeText分为两个版本(2和3),按下Ctrl+B键运行。
在2中使用要搭建Lua环境(有时间会写一下如何搭建使用),而3中集成了Lua语言的功能,不需要搭建就可以直接使用。
(1)Lua语法特点
首先给人的感觉就是简洁,没有过多冗余的”{}“和”;“,区别于其他语言(如C,C#等)。
Lua中的标识符可以是由任意字母、数字、下划线构成的字符串,不能以数字开头。避免使用下划线开头加一个或多个大写字母的标识符,Lua将这类标识符保留用作特殊用途。
Lua区分大小写,用”--“行注释。”--[[ 代码块 ]]“块注释。变量默认声明为全局变量。
访问未初始化的变量不会引发错误,访问结果时nil.
Lua中有8基础类型:nil(空)、boolean(布尔)、number(数字)、string(字符串)、userdata(自定义类型)、function(函数)、thread(线程)和table(表)。
(2)使用Lua语言的一些代码细节
print("This is the first lua program")
if true then
print("Hello")
end
--这是一个注释
a= nil
--[[这是一个多行注释
这是一个多行注释
这是一个多行注释
--]]
print(type("hello"))
print(type(10.3))
print(type(nil))
print(type(true))
print(type(type(10.3)))
a={x=3,y=6}
print(type(a))
a ="one string"
b=string.gsub(a,"one","another")
print(b)
字符串的替换,输出b的值为another string
a="zhang"
b="san"
--local表示局部变量
local sum =a.." "..b
print(sum)
--遇到算数运算符,string与number之间自动转换
a=10
print(a+"1")print(a.."1")
--不加空格会报错,系统认为第一个.表示小数点
print(10 ..1)print(tonumber("10"))
输出结果:
关系运算符:”~“表示非,A and B简单理解就是返回其中第一个false值/nil值,A B全为真返回A; A or B 返回第一个真值,全为false值/nil值时返回第一个。
if 10~="10" then
print("equal")
endprint(4 and 5)
print(nil and 13)
print(false and nil)
print(false and 13)
print(4 or 5)
print(false or 5)
输出结果:
--求两个数中较大值
function max(a,b)
if a>b then
return a
else
return b
end
-- body
end
print("Max:"..max(2,1))
--加法函数
function Add(a,b)
-- body
return a+10,b+10
end
m,n=Add(1,2)
print(m,n)--斐波那契数列
function fabric(n)
if n==1 or n==2 then
return 1
else
return fabric(n-1)+fabric(n-2)
end
-- body
end
print(fabric(3))
输出结果分别是:Max:2 11,12 2
--table的数组形式
local days ={"A","B","C","D"}
print(#days)--只能用于标准的数组格式
print(days[1])
print(table.maxn(days))--遍历的两种形式
for i=1,#days do
print(days[i])
endfor k,v in pairs(days) do
print(k,v)
end--字典形式
local person = {"January","Februray",name="zhangsan",[4]="March",age=20,sex=true}
print(person["name"])
print(#person)
print(table.maxn(person))
person.age=25--person["age"]=50
person.country="China"
--ipairs 只能用于数组形式 pairs都可以 数组字典混合ipairs只遍历数组
--ipairs顺序遍历数组,不能有间隔,[3]="March"可以显示[4]="March"不能显示
for k,v in ipairs(person) do
print(k,v)
end
#数组名等价于table.maxn(数组名) 但是无法用来表示字典形式的长度
字典中访问某个键时可以通过字典名.键名或字典名[”键名“]两种方式访问
关于table库中常用的一些函数:
t={1,2,3}
--头插法
table.insert(t,1,0)
--尾插法
table.insert(t,#t+1,4)
--删除
table.remove(t,2)
table.insert(t,1)
--排序
table.sort(t)
for k,v in pairs(t) do
print(k,v)
end
spring ={"众里寻他千百度","慕然回首","那人却在灯火阑珊处"}
print('逗号链接:',table.concat(spring,","))
--逗号链接: 众里寻他千百度,慕然回首,那人却在灯火阑珊处
print('逗号链接从1位置开始,2位置结束:',table.concat(spring,",",1,2))
--逗号链接从1位置开始,2位置结束: 众里寻他千百度,慕然回首
print('换行显示,从1位置到3位置:\n',table.concat(spring,"\n",1,3))
-- 众里寻他千百度
--慕然回首
--那人却在灯火阑珊处
num={1,2,3,4,5,6}
print('大小比较:',table.concat(num,"<"))
--大小比较: 1<2<3<4<5<6apple={"a","p",[5]="e"}
--返回table中所有元素下标的最大值
print(table.maxn(apple))
print(#apple)
--得到table的长度
print(table.getn(apple))
ta={1,2,[24]=3}
print(table.maxn(ta))
关于Math数学库中常用的函数介绍:
--随机数种子
math.randomseed(tostring(os.time()):reverse():sub(1,6))
print(math.random(1,100))
print(math.random(1,100))
print(math.random(1,100))
print("_______________________")
--圆周率
print(math.pi)
--弧度转角度
print(math.deg(3.14))
--去尾5
print(math.floor(5.4))
--进一6
print(math.ceil(5.4))
关于上述代码中随机数这块我要解释一下:
直接使用os.time系统时间设置随机数的时间种子时,是默认一秒执行一次,因此在一秒执行很多次是很容易的,会出现随机数固定而不在随机,读者可以将print(math.random(1,100))这句代码放到循环体中进行尝试。
math.randomseed(tostring(os.time()):reverse():sub(1,6))用这句代码将时间设为每毫秒执行一次,达到随机数的效果。
关于函数的问题:
print("______________________闭合函数_____________________")
--闭合函数
function count( ... )
-- body
local i=0
return function ( ... )
-- body
i=i+1
return i
end
end
local func=count()--返回的是一个函数而不是值
print(type(func))
print(func())
print(func())
输出结果:function 1 2
print("______________________非全局函数_____________________")
--非全局函数
function A( ... )
-- body
end
--等价于
local B=function ( ... )
-- body
print("func")
end
B()
--[[
--遍历全局变量表
for k,v in pairs(_G) do
print(k,v)
end
]]
local eat
local drink
eat=function ( ... )
-- body
print("eat");
return drink()
end
drink=function ( ... )
-- body
print("drink")
end
eat()
输出结果:func eat drink
在这里要注意:
local function eat()
print("eat")
return drink()
end
local function drink()
print("drink")
end
eat函数里要调用drink函数。但是要注意Lua是解释型语言,逐句解释运行。
在运行的时候,drink函数是通不过的,因为这个时候drink函数未定义,换句话说,drink变量并不存在。
关于尾调用问题:
一个函数的调用是另一个函数的最后一个动作时,这个调用就称之为尾调用。比如这样的函数:
function eat()
return drink()
end
当eat函数调用完drink函数之后,就没有其他事情要做了,所以,调用drink函数,就属于尾 调用。像下面的就不属于尾调用:
function eat()
return drink()+1
end
因为调用完drink函数之后,还要取得drink的返回值,然后进行一次加法操作,这就不符合 定义了。
尾调用有什么好处?
尾调用的时候,该函数也就意味着结束了,不需要保存任何关于该函数的栈信息, 因此可以拥有无数嵌套尾调用。尾调用主要用来实现状态机等操作。
关于迭代器:
print("_____________________迭代器______________________")
--迭代器
function DieDaiQi(t)
local i=0
return function()
-- body
i=i+1
return t[i]
end
-- body
end
t={"A","B","C","D"}
local iter=DieDaiQi(t)
while true do
local value=iter()
if value==nil then
break
end
print(value)
end
for value in DieDaiQi(t) do
print(value)
endfunction DieDaiQiTwo(t)
local i=0
return function ()
i=i+1
if i > #t then
return nil
end
return i,t[i]
end
end
for k,v in DieDaiQiTwo(t) do
print(k..","..v)
end
输出结果:
三、学习总结
主要是初识Lua语言,结合之前学过的C语言、Java语言、C#语言进行对比,很容易发现Lua语言简洁便捷,代码简单,同时出错时能直接显示具体的行数。知识点比较繁琐,杂乱,不过整理后能发现代码的语法跟其他语言是大同小异的。