lua官方英文文档:http://www.lua.org/manual/5.2/

lua中国开发者网址:http://bbs.luaer.cn/

《lua程序设计(第二版)》(闭合函数和闭包,迭代器与泛型for,协同程序,元表和元方法,环境,模块和require,面向对象编程,弱引用table,函数库(数学库、table库、字符串库、操作系统库、调试库和I/O库),lua和C交互API,内存管理和GC,)

《C和C++程序员的lua快速入门》

《lua游戏开发实践指南》

《luabind使用手册》

应该尽量使用 local 变量而非 global 变量。这是 Lua 初学者最容易犯的错误。global 变量实际上是放在一张全局的 table 里的。global 变量实际上是利用一个 string (变量名作 key) 去访问这个 table 。虽然Lua5 的 table 效率很高 ,但是相对于 local 变量,依然有很大的效率损失。local 变量是直接通过 Lua 的堆栈访问的。有些 global 变量的访问是不经意的,比如我们有双重循环操作一个迭代的 table:

for k1,v1 in pairs(tbl) do
for k2,v2 in pairs(v1) do
...
end
end

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

do local pairs=pairs
for k1,v1 in pairs(tbl) do
for k2,v2 in pairs(v1)do
...
end
end
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 } 这样封装一个坐标。不过还有一个方法可供选择。它稍微轻量一点。

function point (x,y)
return function()
return x,y
end
end -- 使用范例
p=point(,)
print(p())-- 输出 1 2

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

function point (x,y)
return function(idx)
if idx=="x" then
return x
elseif idx=="y" then
return y
else
return x,y
end
end
end -- 使用范例
p=point(,)
print(p("x"))--
print(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 把虚表串起来。当类继承层次过多的时候,效率比较低,那么就可以用下面这个技巧。

function inherit(sub,super)
setmetatable(sub,
{ __index=function(t,k)
local ret=super[k]
sub[k]=ret
return ret
end})
end

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

function foo(arg)
arg=arg or"default"
...
end

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

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

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

function max(a,b)
return a>b and a or b
end

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

lua总则的更多相关文章

  1. lua执行字节码的过程介绍

    前面一篇文章中介绍了lua给下面代码生成最终的字节码的整个过程,这次我们来看看lua vm执行这些字节码的过程. foo = "bar" local a, b = "a& ...

  2. lua 学习笔记(1)

    一.lua函数赋值与函数调用         在lua中函数名也是作为一种变量出现的,即函数和所有其他值一样都是匿名的,当要使用某个函数时,需要将该函数赋值给一个变量,这样在函数块的其他地方就可以通过 ...

  3. 在redis中使用lua脚本让你的灵活性提高5个逼格

    在redis的官网上洋洋洒洒的大概提供了200多个命令,貌似看起来很多,但是这些都是别人预先给你定义好的,但你却不能按照自己的意图进行定制, 所以是不是感觉自己还是有一种被束缚的感觉,有这个感觉就对了 ...

  4. 使用Nginx+Lua代理Hadoop HA

    一.Hadoop HA的Web页面访问 Hadoop开启HA后,会同时存在两个Master组件提供服务,其中正在使用的组件称为Active,另一个作为备份称为Standby,例如HDFS的NameNo ...

  5. 打印Lua的Table对象

    小伙伴们再也不用为打印lua的Table对象而苦恼了, 本人曾也苦恼过,哈哈 不过今天刚完成了这个东西, 以前在网上搜过打印table的脚本,但是都感觉很不理想,于是,自己造轮子了~ 打印的效果,自己 ...

  6. lua解析赋值类型代码的过程

    我们来看看lua vm在解析下面源码并生成bytecode时的整个过程: foo = "bar" local a, b = "a", "b" ...

  7. 怎么调试lua性能

    怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...

  8. Lua 安全调用 metatable 的简单应用

    事情的经过 我们的项目中存在好几个战斗界面,不过界面中的内容略有不同.跟同事出去吃饭的时候,他问我.我们现在的战斗界面.有很多是重复的,但是也有偶尔几个地方不太一样.我在战斗过程中驱动这些界面的时候. ...

  9. 让Lua自己把文件夹下面的所有文件自动加载起来吧

    没有想到我也做了一回标题党.其实这里边说的自动还是有夸大其词的部分.其实只是指定文件夹,然后根据指定文件夹数据,加载目录下边的内容而已. 怎么来进行Lua文件的加载 一般情况下,相关的功能需要给他创建 ...

随机推荐

  1. Windows IOT 开发入门(硬件入门)

    接上文,在准备工作完成之后.接下来应该要熟悉硬件和架构了. 以下是一个简易物联网架构设计图 关于微软云这里就不说太多了.有兴趣的朋友可以去这里了解更多https://www.azure.cn/. 在上 ...

  2. 关于Unity中拖尾渲染器的使用

    拖尾渲染器 是一个组件,能够帮我们绘制出拖尾的效果. 就是跟在运动物体后面的东西,前进的过程中,末尾的不断消失,前面的不断生成,有一个长度.长度是以时间计算的,从末尾到头有多少秒的时间就是拖尾的长度. ...

  3. Chrome驱动安装问题

    1.org.openqa.selenium.WebDriverException: unknown error: call function result missing 'value' 原因:浏览器 ...

  4. Window7 Cocos2d-x配置开发环境

    1.到Cocos2d-x官方网下载最新版,解压后在目录cocos2d-x-2.1.5\tools\project-creator\create_project.py 2.安装Python,到网站htt ...

  5. 事件的监听是由awt完成的

    学swing 之前先学awt ,因为awt 是Java实现图形界面的基础. 它能够完成编写界面的基本功能,最重要的是,事件的监听是由awt完成的. 而swing是在awt基础上提供的新的界面工具包,它 ...

  6. 嵌入式驱动开发只设备数---dts

    http://blog.sina.com.cn/s/blog_ad64b8200101e7q0.html

  7. ARM mbed平台WIZwiki-W7500使用说明

    ARM mbed IDE 是ARM内核微控制器的在线开发工具,其站点是:http://developer.mbed.org. 站点提供了在线编译器,不须要本地安装编译器就可以进行开发,因此没有地点.时 ...

  8. SQL Server 存储过程,带事务的存储过程(创建存储过程,删除存储过程,修改存储过

    存储过程 创建存储过程 use pubs --pubs为数据库 go create procedure MyPRO --procedure为创建存储过程关键字,也可以简写proc,MyPRO为存储过程 ...

  9. CentOS下 RabbitMQ单机安装配置

    CentOS RabbitMQ rpm 安装方法: 系统环境:CentOS6IP地址:10.100.62.41 1.erlang安装: erlang下载地址: http://www.rabbitmq. ...

  10. Bioperl 解析blast的输出结果

    用bioperl 解析blast的默认输出结果, 整理成-m8格式的输出 #!/usr/bin/perl use Bio::SearchIO; my ($blast) = @ARGV; my $sea ...