本文相当于《lua程序设计第二版》的一个笔记 (本书一共31章节)
第一章,开始
print("hello world")
将上面这个保存到 hello.lua 文本中,然后 lua hello.lua 就会看到结果了。
来一个阶乘的例子
--定义一个阶乘函数
function fact(n)
if n==0 then
return 1
else
return n*fact(n-1)
end
end
print("enter a number:")
a=io.read("*number")--读取一个数字
print(fact(a))
运行如下:
E:\program\lua 的目录
2015/06/24 10:44 <DIR> .
2015/06/24 10:44 <DIR> ..
2015/06/24 10:41 200 fact.lua
2015/05/19 22:49 298,917 lua53.dll
2015/04/24 01:03 93,861 lua53.exe
2015/05/19 22:51 228,669 luac53.exe
2015/05/19 22:51 95,533 wlua53.exe
5 个文件 717,180 字节
2 个目录 234,745,798,656 可用字节
E:\program\lua>lua53 fact.lua
enter a number:
5
120
E:\program\lua>
1.1 程序块
lua多条语句可以使用也可以不适用分号(;)比如下面的语句是一样的
a=1
b=a*1
-----------
a=1 b=a*2
运行 lua进入交互模式
E:\program\lua>lua53
Lua 5.3.0 Copyright (C) 1994-2015 Lua.org, PUC-Rio
>
1.1未完待续
1.2词法规范
lua的标识符 字母数字下划线(数字不能开头),下划线和大写字母开头在lua中专用特殊用途,lua区分大小写,and是一个保留字,lua的保留字有一下:
--lua 保留字
and break do else elseif end
false for function if in
local nil not or repeat
return then true until while
1.3 全局变量
全局变量不需要声明,比如 a=1 就会产生一个全局变量,lua中访问一个没声明的变量不会发生错误,会得到一个nil
1.4解释器程序
未完待续
第二章 类型和值
--lua有8种基本类型
--nil(空) boolean(布尔) number(数字) string(字符串)
--userdata(自定义类型) function(函数) thread(线程) table(表)
print(type("hello world"))--string
print(type(10.4*3))--number
print(type(print))--function
print(type(type))--function
print(type(true))--boolean
print(type(nil))--nil
print(type(type(X)))--string
lua中函数是作为第一类值对待
2.1 nil(空)
全局变量赋值前就是nil ,将nil赋值给一个全局变量相当于删除它,nil(无效数值)
2.2 boolean
lua中除了 false和nil,其他都是真
2.3 number
number 类型表示实数, 4 ,0.4, 4.75e-3
2.4 string
未完待续
2.5 table 表
未完待续
2.6function(函数)
未完待续
第三章 表达式
lua 支持的算术操作符有+-*/%就基本的这些都有
3.2 关系操作符
<,>,<=,>=,~=(不等) nil只与自身相等。
字符串比较是按字母次序。
数字和字符串之外的其他类型只能进行相等性或不等性比较。
3.3逻辑操作符
逻辑运算符 and or not ,
and和or使用“短路求值”
3.4字符串连接
字符串连接是“..”(两个点)操作符
a="hello "
print(a.."world")--hello world
3.5 优先级
1. ^
2. not # -
3. * / %
4. + -
5. ..
6. < > <= >= ~= ==
7. and
8. or
3.6 table构造式
待续
第四章
4.1赋值
lua允许多重赋值a,b=1,2这样,交换a,b=b,c 如果有多余的则赋值为nil,也就是静静的丢弃掉
4.2局部变量与块
j=10 --全局变量
local i=1 --局部变量,通过local语句创建局部变量
局部变量的作用域仅限于声明他们的那个快,一个快是一个控制结构的执行体,或者是一个函数的执行体,再或者是一个程序块
x=10
local i=1 --程序块中的局部变量
while 1<=x do
local x=i*2 --while循环体中的局部变量
print(x) --2,4,6,8
i=i+10
end
if i>20 then
local x --then 中的局部变量
x=20
print(x+2) --如果测试成功会打印22
else
print(x) --10 全部变量
end
print(x) --10 全部变量
尽可能使用局部变量是一个好的编程习惯
在lua中 local foo=foo 将全部变量赋值给局部变量
4.3控制结构
if a<0 then a=0 end
嵌套if可以使用elseif可以避免潜逃中出现的多个end
if op=="+" then
r=a+b
elseif op=="-" then
r=a-b
else
error("ddddd")
end
while
local i=1
while a[i] do
print(a[i])
i=i+1
end
repeat
line=io.read()
until line~=""
print(line)--repeat中的局部变量在until中仍然可以访问到
数字for
for i=1 ,f(x) do print(i) end--第三个表达式可选的,如果不指定则加1
for i=1 ,f(x),-1 do print(i) end
泛型for
for k in pairs(t) do print(k) end
4.4break与return
break和return 没啥好说的。
第五章 函数
一个函数若只有一个参数,并且此参数是一个字面字符串或者table构造式,那么圆括号可有可无,如:
print "hello world" --print("hello world")
dofile 'a.lua' --dofile('a.lua')
print[[a multi-line message]] --print([[a multi-line message]])
f{x=10.y=20} --f({x=10.y=20})
type{} --type({})
lue为对象式调用提供了一种特使的用法-冒号操作符:o.foo(o,x) 另一种写法o:foo(x)
function f(a,c) return a or b end--一个函数
f(3)--a=3 b=nil
f(3,4)--a=3,b=4
f(3,4,5)--a=3,b=4,5被丢弃
5.1多重返回值
s,e=string.find("hello Lua users","Lua")
print(s,e)--7 9这是一个多返回值
5.2变长参数
function add(...)
local s=0
for i,v in ipairs{...} do
s=s+v
end
return s
end
print(add(3,4,10,25,12))--54可变参数
5.3具名实参
待续
第六章 深入函数
6.1 closure闭合函数
若一个函数写在另一个函数的内部,内部的函数可以访问外部函数的局部变量,这个叫做“词法域”。
--这是一个对学生姓名进行排序的例子
names={"Peter","Paul","Mary"}
grades={Mary=10,Paul=7,Peter=8}
table.sort(names,function(n1,n2)
return grades[n1]>grades[n2]--比较年级
end)
--假设我们要自己实现这个例子
function sortbygrade(names,grades)
table.sort(names,function()
return grades[n1]>grades[n2]--比较年级
end)
end
--在这里例子中匿名函数是函数可以访问grades
--而grades是sortbygrade的局部变量。在这个匿名函数的内部,grades
--既不是全局变量也不是局部的,在lua中叫做"非局部的变量"
--附:这个其实就是自由变量了。
为什么lua允许这样访问呢,原因在于函数是”第一类值”(先解释第一类值
在JavaScript中 var c=function(){} 这样可以把一个函数赋值给一个变量,函数和number一样,这样的语言就是 所谓的第一类值,比如java中,就没办法这么做。)
function newCounter()
local i=0
return function()
i=i+1
return i
end
end
---------------
c1=newCounter()
print(c1())--1
print(c1())--2
----------------
c2=newCounter()
print(c2())--1
print(c1())--3
print(c2())--2
--如上 书上这么说的 从技术上讲,Lua中只有closure 而不存在"函数" 因为函数本身就是一种特殊的clousure
--注意 在这里创建闭合函数的时候其实做了一个i的副本。就是说有几个闭包就有几个i的副本。
--这个其实也没啥。他只有可能这么干。
这段代码我翻译成js试试 如下,结果是一致的,他只有可能这么干
function newCounter(){
var i=0
return function(){
i=i+1
return i
}
}
//---------------
var c1=newCounter()
console.log(c1())//1
console.log(c1())//2
//----------------
var c2=newCounter()
console.log(c2())//1
console.log(c1())//3
console.log(c2())//2
6.2非局部的函数
没啥说的,意思函数可以存放table中,存放到其他数据结构中
6.3正确的尾调用
lua支持尾递归优化,赞。虽然语言支持尾递归,但是必须写出尾递归的代码才行。
function foo(n)
if n>0 then return foo(n-1) end
end
--比如这个代码,无论n是几,都不会出现栈溢出。因为程序不需要记录之前栈调用。这个代码在java中试了一下java.lang.StackOverflowError ,果然java不支持尾递归。
在lua中,只有 return[func][args]这样才算是“尾调用”
lua尾调用待续
附录:
① -#是表的长度运算符 t = {“a”, “b”, “c”, “d”},#t –输出是4
②:
Lua中的
loadfile只加载文件,啥都不做
dofile加载文件并且执行文件的内容
require加载文件并且只执行一次