您的位置:首页 > 编程语言 > Lua

Lua程序设计笔记之二: 操作符/语句

2013-07-15 23:16 218 查看
一. 操作符
1. +(加) -(减) *(乘) /(除) ^(指数) %(取模) -(负号)
2. 关系操作符: <    >    <=    >=    ==   ~=
3. 逻辑操作符: and or false   (and 和 or都使用“短路求值”)
4. table的初始化风格分为记录风格的初始化以及列表风格的初始化;不推荐在lua中以0作为数组的起始索引;在一个构造式中,可以使用分号代替逗号,用于分隔构造式中不同的成分。
===================================================
二. 语句
1. Lua允许"多重赋值",也就是一次将多个值赋给多个变量,每个值或每个变量之间用逗号分隔,lua会先对等号右边的所有元素求值,然后才执行赋值。
2. 使用local来声明一个局部变量,局部变量的作用域仅限于声明它们的那个块,一个块(block)是一个控制结构的执行体,或者是一个函数的执行体或者是一个程序块(chunk);如果需要严格地控制某些局部变量的作用域时,使用do-end块来控制。
3. 在lua中,有一种习惯用法:local foo = foo,创建一个局部变量,使用全局变量来初始化
4. lua提供了一组传统的小巧的控制结构,包括用于条件执行的if,用于迭代的while, repeat,for。所有的控制结构都有一个显式的终止符: if,for和while以end作为结尾,repeat以untile作为结尾。控制结构中的条件表达式可以是任何值,lua将所有不是false和nil的值视为“真”;
5. 对于for语句,分为两种形式,数字型for(numeric for)和泛型for (generic for)
6. 数字型for,var从exp1变化到exp2,每次变化都以exp3作为步长(step)递增var,并执行一次"执行体",exp3可选,不知指定的话,会默认将步长设为1
for var=exp1,exp2,exp3 do
     <执行体>
end
在这里需要注意的是,首先,for的3个表达式是在循环开始前一次性求值的,其次,控制变量会被自动地声明为for语句的局部变量,并且仅在循环体内可见,循环结束后,控制变量就不在了
4. 泛型for (generic for),泛型for循环通过一个迭代器(iterator)函数来遍历所有值,lua基础库提供了ipairs,用于遍历数组的迭代器函数。
泛型for循环与数字型for循环有两个相同点:1)循环变量是循环体的局部变量 2)决不应该对循环变量作任何赋值
for k,v in pairs(table) do

end

===================================================

三. 函数
1.无论哪种用法都需要将所有参数放到一对圆括号中,即使调用函数时没有参数,也必须写出一对空括号,对于此规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字面字符串或者table构造式,那么圆括号是可有可无的
2. Lua为面向对象式的调用提供了一种特殊的语法--冒号操作符,表达式 o.foo(o, x)的另外一种写法o:foo(x),冒号操作符使调用o.foo时将o隐含地作为函数的第一个参数。
3. Lua中具有一项非常与众不同的特征,允许函数返回多个结果。以Lua编写的函数返回多个结果,只需在return关键字后面列出所有的返回值即可。对于多重返回值,有下面一系列规则需要注意:
1) 在多重赋值中,若一个函数调用是最后(或仅有的)一个表达式,那么lua会保留其尽可能多的返回值
2) 如果一个函数没有返回值或者没有返回足够多的返回值,那么Lua会用nil来补充缺失的值
3) 如果一个函数调用不是一系列表达式的最后一个元素,那么将只产生一个值
4) 当一个函数调用作为另一个函数调用的最后一个(或仅有的)实参时,第一个函数的所有返回值都将作为实参传入第二个参数。
5) table构造式可以完整地接收一个函数调用的所有结果,即不会有任何数量方面的调整,不过这种行为只有在函数调用作为最后一个元素时才会发生,而在其他位置上总会只有一个结果值
6) return f(); 这样的语句,将会返回f()返回的所有返回值,而将一个函数调用放入到一对圆括号中时,会迫使函数只返回一个结果,如 return (f());
4. unpack函数,是一个特殊函数,它接受一个数组作为参数,并从下标1开始返回该数组的所有元素;unpack的一项重要用途体现在"泛型调用(generic call)"机制中,泛型调用机制可以动态以任何实参调用任何函数。
5. Lua函数可以接受不同数量的实参,声明函数中,使用3个点作为最后一个参数,表示可变参数,"…";但是在函数中,通过一个隐含的局部变量"arg"来接受所有的变长参数,这个table还有一个名为"n"的字段,用来记录变长参数的总数;在这里,只有在需要的时候才会去创建用于变长参数访问的table
6. Lua中的参数传递机制是具有"位置性的",Lua的函数并不直接支持具名实参,但是可以用使用table来传递参数达到这样的效果
===================================================
四. 深入函数
1. 在Lua中,函数是一种"第一类值(First-Class Value)",它们具有特定的词法域(Lexical Scoping)。
“第一类值”:表示在Lua中,函数与其他传统类型的值(例如数字和字符串)具有相同的权利
"词法域": 指一个函数可以嵌套在另一个函数中,并且内部函数可以访问外部函数中的变量
2. 在Lua中,有一个容易混淆的概念是,函数与所有其他值一样都是匿名的,即它们都没有名称。
function foo (x) … end 只是 foo = function (x) … end的一种语法糖而已,跟声明其他变量是一样的
3. 闭合函数(closure):简单地讲,一个closure就是一个函数加上该函数所需访问你的所有"非局部的变量"。从技术上讲,Lua中只有closure,而不存在"函数",因此,函数本身就是一种特殊的closure。
4. 非全局的函数(non-global function): 
1)在table中定义函数
方法一: lib = {};
lib.foo  = function (x, y) … end
方法二:lib = {foo = function (x, y) … end}
方法三:lib = {};
function lib.foo (x, y) …. end;
3) 其实,在这里,只要将一个函数存储到一个局部变量中,既可以得到一个"局部函数",也就是说该函数只能在某个特定的作用域中使用,这个跟定义变量有相似的地方。lua提供了一个"语法糖"来创建一个局部函数
local function foo (<参数>) <函数体> end 
上面的定义方法就等价于下面这种展开式的定义
lcoal foo;
foo = function (<参数>) <函数体> end
2) 在定义递归的局部函数时,有一个特别之处需要注意,上面的那种技巧对于递归函数是无效的,需要使用前向声明(forward declaration)的方式来解决这个问题,同样的问题也出现在间接递归的身上。
local foo;
foo =function ()
<一些代码>foo() <一些代码>
end
3) 尾调用(proper tail call):lua中的函数还有一个有趣的特征,lua支持"尾调用消除(tail-call elimination)",所谓尾调用就是一种类似于goto的函数调用,当一个函数调用是另外一个函数的最后一个动作时,该调用才算是一条"尾调用",如function f (x) return g(x) end
由于,f调用完g之后无其他事情可做,这时程序就不要再保存关于f的栈信息了,g完成调用之后,直接返回调用f的那个点上,这种称为"尾调用消除"。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: