1.JIT可以编译优化清单
http://wiki.luajit.org/NYI
2.lua数组的下标是从1开始的
在没有指定赋值的情况下。C语言的数组下标是从0开始的。
3.逻辑表达式and or not用法
local a = b and C or d
在不确定C是否为真的情况下不要使用,会产生歧义
4.正常情况下,table变是不允许使用负数,运算符作为table的key值。
此时可以使用['*']or["+"]来进行修饰。
5.局部变量与全局变量
使用do-end可以指定执行某一块中的代码
在没有显性使用local修饰时,操作的都是全局变量。
a = 6 --全局变量
local b = 8 --局部变量
“尽可能的使用局部变量”是一种良好的编程风格。局部变量可以避免将一些无用的名称引入全部变量,避免搞乱了全局环境。此外,访问局部变量比访问全局变量更快。最后,一个局部变量通常会随着其作用域的结束而结束,这样lua的垃圾收集器可以释放该值。
在lua中有一种习惯的写法: local foo = foo
这句代码创建了一个局部变量foo,并使用全局变量foo的值来初始化它,如果后续全局变量foo的值改变了,局部变量foo的值也还是之前全局变量foo的值。
eg:local print = print
- local upper = string.upper
- local concat = table.concat
6.lua中的控制结构
所有的控制结构都有一个显式的终止符:if, for, while 以end作为结尾,repeat以until结尾
local i = x/2
repeat
- local error = math.abs(i^2 - x)
- until error < x/1000 --在此处仍可以访问error
7.关于泛型for循环
标准库提供了几种迭代器,包括用于迭代文件中每行的(io.lines),迭代table元素的(pairs),迭代数组元素的(ipairs),迭代字符串中单词的(string.gmatch)等。
注意:1.循环变量是循环体内的局部变量 2.绝不应该对循环变量做任何赋值。
8.lua为面向对象式的调用提供了一种特殊的语法--冒号操作符。
表达式o.foo(o, x)的另一种写法 o:foo(x)
冒号操作符使调用o:foo时将o隐性地作为函数第一个参数。
9.如果函数调用不是一系列表达式的最后一个元素,那么将只返回一个值
local function foo2() return "a","b" end
local x,y = foo2(), 20
最后得到的值:x="a",y=20
10.在函数调用中,参数中的3个点(...)表示该函数可接受不同数量的实参
luajit2不能jit编译这种变长参数的用法,只有解释执行,所有对性能要求高的代码,应避免使用
-
eg: local function foo(a, b, c) return a,b,c end
select (index, ···)
如果 index 是个数字, 那么返回参数中第 index 个之后的部分; 负的数字会从后向前索引(-1 指最后一个参数)。 否则,index 必须是字符串 "#", 此时 select 返回参数的个数。
11.在函数调用中,当实参只有一个table表达式时,函数调用中的圆括号是可有可无的。
local function rename(arg)
- return os.rename(arg.old, arg.new)
函数调用:rename{old = "txt.1", new = "txt.2"} --此时圆括号可以被省略
如果一个函数拥有大量的参数,而其中大部分参数是可选的,那么使用table的形式去接收参数会特别的有用
12.简单的实现函数重写,使用闭合函数(closure)
do
- math.sin = function(x) --这是一个匿名函数
- return oldsin(x*k) --调用的k既不是全局变量也不是局部变量,称其为"非局部的变量"
--注意:在匿名函数中修改k的值,会直接影响其外部函数的k的值
13.高阶函数,函数嵌套使用
--对于特定的函数func调用derivative(func)将近视的返回其倒数
function derivative(func, delta)
-
return (func(x + delta) - func(x)) / delta
- --调用:c = derivative(math.sin)
- print(math.cos(10), c(10))
14. 非全局的函数
local fact= function(n) local fact
- if n == 0 then return 1 fact= function(n)
- else return n*fact(n-1) if n == 0 then return 1
- end else return n*fact(n-1)
end end
end
--lua编译到函数体调用fact(n-1)的地方时,由于局部fact还没有定义完毕,此时调用的是全局的fact,而不是该函数本身。
15.函数的尾调用 -->"尾调用消除" 迷宫游戏
function f(x) return g(x) end
也就是说,当f调用完g之后就再也没有其它事情可做了。所以在"尾调用"之后,程序也不需要保存任何关于该函数的栈信息。即函数再进行"尾调用"时不耗费任何栈空间。
有一点需要注意的是,当想要受益于"尾调用消除"时,务必要确定当前的调用是一条"尾调用"。判断的准则"一个函数再调用完另一个函数之后,是否就无其他事情需要做了"。
以下所有调用都不符合标准:
1.return g(x) + 1 --必须要做一次加法
2.return x or g(x) --必须调整为一个返回值
3.return (g(x)) --必须调整为一个返回值
标准的调用:
return x[i].foo(x[j] + a*b, i + j)
16.有名函数的定义本质上是匿名难书对变量的赋值。
function foo() 等价于 foo = function()
end end
local function foo() 等价于 local foo = function()
end end
17.lua的算术运算符有:
+(加),-(减),*(乘),/(除),^(指数),%(取余)
eg:
- print(2^10) ==> 即求2的10次方,结果:1024
18.lua中的关系运算符:
- <(小于), >(大于), <=(小于等于), >=(大于等于), ==(恒等于), ~=(不等于)
在使用"=="做等于判断时,要注意table,userdata和函数,lua是作引用比较的。也就是说,只有两个变量引用同一个对象时,才认为他们是相等的 。
- eg:local a = {x = 1, y = 2}
- 特别点:lua字符串的相等性比较时间复杂度为o(1);而在其他语言是o(n),逐个比较
19.lua逻辑运算符:
and(逻辑与), or(逻辑或),not(逻辑非)
所有逻辑操作符将false和nil视为假,其他任何值都是真(包括0和空字符串)
20.lua字符串连接:
连接两个字符串可以使用操作符".."
注意:如果其中任意一个操作符是数字的话,lua会将这个数字转换成字符串再连接
- 连接操作符只会创建一个新的字符串,而不会改变原操作数
lua字符串本质上是只读的,因此字符串连接运算符几乎总会创建一个新的(更大的)字符串。这意味着如果有很多这样的连接操作(比如在循环中使用".."拼接最终结果),则性能损耗非常大。这种情况下,推荐使用table和table.concat()来进行多字符串的拼接。
21.lua运算符优先级:
22.使用函数的好处:
1.减低程序的复杂性:把函数作为一个独立的模块,写完函数后,只关心它的功能,而不再考虑函数里面的细节。
2.增加程序的可读性:当我们调用math.max()函数时,很明显该函数就是用于获取最大值的,实现细节就不关心了。
3.避免重复代码:当程序中有相同的代码部分时,可以把这部分写成一个函数,通过调用函数来实现这部分代码的功能,节约空间,减少代码长度。
4.隐含局部变量:在函数中使用局部变量,变量的作用范围就不会超出函数,这样他就不会给外界带来干扰。
23.lua字符串操作
24.lua模块的使用
|
请发表评论