Lua编程技巧学习教程

移动开发 iOS
虽然Lua5 的 table 效率很高 ,但是相对于 local 变量,依然有很大的效率损失。local 变量是直接通过 Lua 的堆栈访问的。有些 global 变量的访问是不经意的,比如我们有双重循环操作一个迭代的 table。

Lua编程技巧学习教程是本文要介绍的内容,主要是来学习LUA的编程技巧,以便可以更方便的去学习,先来本文详细内容讲解。Lua 的 5.1 版本已经正式发布。现在,我们应该把全部讨论放在这个版本上。

应该尽量使用 local 变量而非 global 变量。这是 Lua 初学者最容易犯的错误。global 变量实际上是放在一张全局的 table 里的。global 变量实际上是利用一个 string (变量名作 key) 去访问这个 table 。

虽然Lua5 的 table 效率很高 ,但是相对于 local 变量,依然有很大的效率损失。local 变量是直接通过 Lua 的堆栈访问的。有些 global 变量的访问是不经意的,比如我们有双重循环操作一个迭代的 table:

  1. for k1,v1 inpairs(tbl)dofor k2,v2 inpairs(v1)do  
  2.         ...   
  3.     end  
  4. end 

这里,pairs 其实是一个全局变量应用的函数。如果我们这样做:

  1. dolocalpairs=pairs  
  2.     for k1,v1 inpairs(tbl)dofor k2,v2 inpairs(v1)do  
  3.             ...   
  4.         endend  
  5. end 

效率会稍微提高一些。如果是单层循环,这样做就没有意义。因为 for ... in 循环中的 pairs 这个函数只会被调用一次,而不是每次循环都去调。我们的原则其实是,被多次读取的 global 变量,都应该提取出来放到 local 变量中。

警惕临时变量 字符串的连接操作,会产生新的对象。这是由 lua 本身的 string 管理机制导致的。lua 在 VM 内对相同的 string 永远只保留一份*** copy ,这样,所有字符串比较就可以简化为地址比较。这也是 lua 的 table 工作很快的原因之一。这种 string 管理的策略,跟 java 等一样,所以跟 java 一样,应该尽量避免在循环内不断的连接字符串,比如 a = a..x 这样。每次运行,都很可能会生成一份新的 copy 。

同样,记住,每次构造一份 table 都会多一份 table 的 copy 。比如在 lua 里,把平面坐标封装成 { x, y } 用于参数传递,就需要考虑这个问题。每次你想构造一个坐标对象传递给一个函数,{ 10,20 }  这样明确的写出,都会构造一个新的 table 出来。要么,我们想办法考虑 table 的重用;要么,干脆用 x,y 两个参数传递坐标。

同样需要注意的是以 function foo (...) 这种方式定义函数, ... 这种不定参数,每次调用的时候都会被定义出一个 table 存放不定数量的参数。

这些临时构造的对象往往要到 gc 的时候才被回收,过于频繁的 gc 有时候正是效率瓶颈。

使用 closure 代替 table 上面提到封装坐标的问题。诚然,我们可以用 { x=1,y=2 } 这样封装一个坐标。不过还有一个方法可供选择。它稍微轻量一点。

  1. function point (x,y)returnfunction()return x,y end  
  2. end 

使用范例

  1. p=point(1,2)print(p())-- 输出 1  2  

如果你愿意,还可以做的复杂一点:

  1. function point (x,y)returnfunction(idx)if idx=="x"thenreturn x  
  2.   elseif idx=="y"thenreturn y  
  3.   elsereturn x,y endend  
  4. end 

使用范例

  1. p=point(1,2)print(p("x"))-- 1print(p("y"))-- 2  

x,y 实际被存放在 closure 里,每次调用 function point 都有一份独立的 closure。当然,function 的 code 只有一份。

设法减少从 C 向 Lua 传递字符串 字符串常量在 Lua VM 内部工作的非常快,但是一个从 C 向 lua vm 通过 lua_pushstring 之类的 api 传递进 VM 时,就需要掂量一下了。这至少包含一个再 hash 和匹配的过程。我的 Blog 上的一篇文章讨论了这个问题。

lua 中的继承 lua 中实现 OO ,虚表往往设置一个 metatable 并设置 __index ,而继承则用 metatable 的 __index 把虚表串起来。当类继承层次过多的时候,效率比较低,那么就可以用下面这个技巧。

  1. function inherit(sub,super)setmetatable(sub,  
  2.      { __index=function(t,k)local ret=super[k]  
  3.              sub[k]=ret  
  4.              return ret  
  5.      end})end 

利用逻辑运算的短路效应 lua 编程中,and or 跟 C 一样是有短路效应的,不过他们的返回值并非 bool 类型,而是表达式中的左值或者右值。我们常常利用这个特性来简化代码。

  1. function foo(arg)  
  2.      argarg=arg or"default"  
  3.      ...  
  4. end 

利用 or 运算赋缺省值是最常用的技巧。上例中,如果 arg 为 nil ,arg 就会被赋值为 "default" 。但是这个技巧有个缺陷,当缺省值是 true 的时候会有点问题。

a=a ortrue-- 错误的写法,当 a 明确写为 false 的时候,也会被改变成 true 。
a= a ~= false-- 正确的写法,当 a 为 nil 的时候,被赋值为 true ;而 false 则不变。

另外,巧妙使用 and or 还可以实现类似 C 语言中的 ?: 三元操作:

  1. functionmax(a,b)return a>b and a or b  
  2. end 

上面这个函数可以返回 a 和 b 中较大的一个,其逻辑类似 C 语言中的 return (a>b) ? a : b ;

小结:Lua编程技巧学习教程的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-09-01 16:45:15

J2MELua

2011-08-25 13:44:11

LUA下载SciTE

2011-08-23 15:34:56

Lua模式 匹配

2011-08-24 11:03:33

LUA环境 安装

2011-08-24 14:14:13

LUA环境 配置

2011-08-23 16:37:05

Lua数学库

2011-08-24 15:22:09

2011-08-24 15:42:38

LUA源代码

2011-08-24 15:34:44

MinGWLua环境配置

2011-08-25 15:41:42

Lua源码

2011-08-24 17:09:35

LUA闭包函数

2011-08-24 17:05:01

Lua

2011-08-25 16:38:06

EditPluslua

2011-08-23 16:59:16

C++LUA脚本LUA API

2011-08-24 11:08:09

Lua

2011-08-11 16:19:11

iPhoneCocoa

2011-08-25 16:20:33

Lua脚本变量

2011-08-22 18:08:09

Lua脚本

2010-03-05 13:46:12

Android编程学习

2011-08-31 15:41:38

Lua解释器
点赞
收藏

51CTO技术栈公众号