标签:overflow ext 移动应用 匹配 方式 参考手册 ogr multi nes
来源: http://blog.csdn.net/xoyojank/article/details/12762909
在我使用Lua编程整整9个月后, 是时候停下来反省一下这段经历了. 过去了几年里, 我使用了各式各样的语言:Perl (soaplite.com, 还有其它的项目, 包括我现在的咨询工作), C (DHCPLite 和 ping-pong juggling robot), JavaScript (Google Maps相关经验 和 canvas), MATLAB (ping-pong juggling robot), 等等, 从Turbo Pascal 到 F# -- 比较一下Lua和我接触过的其它语言是一件非常好玩的事情. 我已经使用Lua完成了一些不同类型的项目: 一个远程调试器(MobDebug), 扩展了一个LuaIDE (ZeroBrane Studio), 一个移动应用程序 (LuaRemote), 一些教育性的脚本 (EduPack), 还有一个使用Lua在浏览器画板上进行绘图的demo.
虽然我已经见过很多提到Lua的好和坏的列表 (例如, Lua的优势, 为什么使用Lua, 为什么Lua没有得到广泛地应用, Lua的优点,Lua的好和坏, Lua对比JavaScript, 还有Lua的陷阱), 但是有些特性坑死爹了, 还有些他们忘了提, 所以我就自己搞了个列表. 虽然这说不上非常专业, 也没有覆盖到语言的每个方面 (如 math 和string 库), 但这是根据我的编程语言经历得出来的.
lua
.nil
) , 还可以使用任意类型的值进行索引 (除了 nil
): {1, 2, 5, foo = "bar", [func] = "something", ["some spaces"] = value()}
.return functioncall()
.local function foo() ... foo() ... end
; 注意这样不行 local foo = function() ... foo() ... end
.return 1, 2, 3
. 调用者可以认为返回值是任意个数的: 如果多于3个, 其余会被丢弃; 如果少于3个, 那其它的会是未初始化的 nil
.function foo(...) local args = {...}; bar(param, ...) end
.unpack
(或 Lua 5.2的 table.unpack
): print(unpack({1, 2, 3}))
打印1 2 3
.Lua 5.1中的getfenv
和setfenv
和Lua 5.2中的_ENV
操作), 此外还可以构造 沙盒 .local a, b, c = 1, 2
, x, y = y, x
, or a, b = foo()
.[[...]]
; 可以使用 [[...[=[...]=]...]]
)包含和注释 (--[[...]]
).a = f; (g).x(a)
).for
语句有两种形式: generic (使用迭代器: for a in iter() do ... end
) 和 numeric (使用数字: for a = 1, 5, 0.1 do ... end
); 数字的这个支持各种类型的步进 (不仅仅是整数).f‘string‘
, f"string"
, f[[string]]
, andf{table}
)和方法调用(obj:m()
).nil
会从表中删除它. 这就是说对于不存在的值返回 nil
, 所以元素存不存在跟它是不是 nil
是同一个问题. a = {b = nil}
产生一个空表.object:method(args)
的写法, 与 object.method(object, args)
的写法是等价的, 但 object
只取值一次.nil
和false
是仅有的表示假的值; 0, 0.0, "0" 等其它的一切值都是true
.if a ~= 1 then ... end
).not, or, and
操作符是逻辑运算符.a=b=1
或if (a=1) then ... end
的写法.a+=1
, a++
, 或其它简写形式.continue
语句, 尽管有一个 解释 和一堆的替代品, 如在循环中使用 repeat break until true
跳出 或者使用一个Lua 5.2中的goto
语句.switch
语句.a = {}; a.field
正常, 但{}.field
不行; 后者需要这样写 ({}).field
.for
循环中的极限和步进值是 缓存过的; 这意味着 for i = init(), limit(), step() do ... end
中的三个函数 init
, limit
, 和step
只在循环开前调用过一次.0 == "0"
为false
, {} ~= 1
为 true
, 还有foo["0"]
和foo[0]
引用的是表中不同的值; 其它关系运算符会在比较不同类型的值时产生错误.a = {a = 1, b = 2, }
.pcall
和error
的组合十分强大, 特别是 error
可以返回任何东西 (例如一个表)而不是仅仅是一个字符串, 但是 catch ... finally
结构在多数情况下可能更加清晰直观.string.len
和模式识别函数需要识别 Unicode 字符); 不过有一个ICU库的 绑定 实现了Unicode支持. 可以看一下这条 消息 和后续总结的的关于现有的支持和string.*
需要什么样的修改.(group )?
, 还有组内组), 没有任何一个都是会增加实现复杂度的. 对于需要更强大的正则表达式的人可以使用 LPeg 和它的 re 模块.foo = test and value1 or value2
形式, value2
在test
和value1
都为 false
时可以赋值.getenv
和setenv
[6/1/2012更新] miko 在评论中提到, 有 os.getenv, 但是没有相应的 os.setenv
.coroutine.yield
在跨越 Lua/C 边界调用时会失败 attempt to yield across metamethod/C-call boundary
. 我在使用 luasocket和协程进行异步编辑时多次遇到过这个错误, 最后使用 copas 模块解决. 在Lua 5.2中这个问题得到解决.nil
). Lua中的表有两部分: "数组" 部分(使用 t = {1, 2, 3}
生成) 和 "哈希" 部分(使用t = {a = "foo", ["b"] = 2}
生成); 这两者可以灵活地结合在一起. #table
返回最短的"数组"部分长度(没有任何缺口) 而table.maxn(t)
返回最长的 "数组" 部分(Lua 5.2移除了这个函数). "哈希" 部分没有定义长度. 两者都可以使用 pairs
方法进行遍历, 同时允许你对其中的元素进行计数. 然而, print(#{1, 2, nil, 3})
打印4 却不是想像中的 2 ,print(#{1, 2, nil, 3, nil})
打印的则是2. 我确信有一个合理的理由解释它, 但是现在说是就是"坑爹"的地方. [11/17/2012更新] FireFly 在评论中提到, Lua 5.2 中表的长度 只定义成 没有洞的.return
必须是语句块中的最后一句; 也就是说,function foo() print(1); return; print(2) end
会触发一个错误 ‘end‘ expected...
或 unexpected symbol near <whatever statement you have after ‘return‘>
(这取决于在return
之后有没有分号). 没有人会这样写, 除非你在调试, 但我却被它坑了好几次. 原本我想把它放进"与众不同的"分类, 但是我发现它前后矛盾. 在一个不能使用 return
的地方却能使用 do return end
. [5/19/2012更新] 这同样出现在 break
语句上, 虽然在Lua 5.2中 break
不再必须是语句块的最后一句了. function f123() return 1, 2, 3 end
function f456() return 4, 5, 6 end
print(f123(), f456()) -- prints 1, 4, 5, 6
print(f456(), f123()) -- prints 4, 1, 2, 3
这个 return
的行为也受到这条规则约束: return f456()
返回3个值, 但return (f456())
只返回一个值 (注意多出的括号). 关于这个语言特性有 很好的文档, 但我仍然认为它太坑爹了 (或许在旁人看来它是优点).总的来说, 到目前为止我很享受这个语言带来的简洁和便利, 尽管有些东西跟我之前的做法有点不一样. 特别是在8岁的儿子很快地学会了Lua的语法后, 我觉得自己的那些关于 Turbo Pascal 的经历已经过时了.
标签:overflow ext 移动应用 匹配 方式 参考手册 ogr multi nes
原文地址:http://www.cnblogs.com/lsgxeva/p/7745836.html