lua学习笔记
使用命令行参数-i来启动lua解释器,那么解释器就会在运行完指定的程序块后进入交互模式。
1 | test.lua |
1 | lua -i test.lua |
另一种运行程序块的方式是使用函数dofile,该函数会立即执行一个文件。
行注释
1 | -- here |
块注释
1 | --[[ |
类型与值
在lua中有8种基础类型:nil,boolean,number,string,userdata,function,thread,table
函数type可根据一个值返回其类型名称:
1 | print(type(type)) -- function |
lua将值false和nil视为“假”,而除此之外的其他值视为“真”。
lua提供运行时的数字与字符串的自动转换。在一个字符串上应用算数操作时,lua会尝试将这个字符串转换成一个数字:
1 | print("10" + 1) -- 11 |
lua不仅在算数操作中会使用这种强制转换,还会在其他任何需要数字的地方这么做,反之亦然:
1 | print(10 .. 20) -- 1020 |
a.x和a[“x”]等价
关系操作符
操作符==和~=用来做相等测试,如果两个值具有不同的类型,lua就认为它们不相等。否则,lua会根据它们的类型来比较两者。对于table,userdata和函数,lua是作引用比较。
只能对两个数字或两个字符串作大小性比较。lua是按字母次序来比较字符串的,具体的字母次序取决于对lua的区域设置。
lua操作符优先级(从高到低):
1 | ^ |
在二元操作符中,除了指数操作符^和连接操作符..是右结合,所有其他操作符都是左结合。
1 | a + i < b / 2 + 1 -- (a + i ) < ((b / 2) + 1) |
语句
lua允许多重赋值
1 | a, b = 10, 2 |
尽可能地使用局部变量是一种良好的编程风格,局部变量可以避免将一些无用的名称引入全局环境,避免扰乱了全局环境。此外,访问局部变量比访问全局变量更快,。最后一个局部变量通常会随着其作用域的结束而消失,这样便使垃圾收集器可以释放其值。
控制结构:
if-else-then:
1 | if cond then |
while:
1 | while cond do |
repeat:
1 | repeat |
对于lua的repeat语句来说,一个声明在循环体中的局部变量的作用域包括了条件测试。
函数
调用函数无论哪种方法都需要将所有参数放到一对圆括号中。即使调用函数时没有参数,也必须写出一对空括号。对于此规则只有一种特殊的例外情况:一个函数若只有一个参数,并且此参数是一个字面字符串或者table构造式,那么圆括号便是可有可无的:
1 | print "hello world" |
lua函数可以返回多个值,如果一个函数没有返回值或者没有足够多的返回值,那么lua会用nil来补充缺失的值:
1 | function () |
unpack函数接受一个数组作为参数,并从下标1开始返回该数组的所有元素:
1 | print(unpack{10, 20, 30}) -- 10 20 30 |
参数表中使用3个点(…)表示该函数可接受不同数量的实参,表达式“…”的行为类似于一个具有多重返回值的函数,它返回的是当前函数的所有变长参数。
在lua中,函数是第一类值,它们具有特定的词法域。“第一类值”表示在lua中函数与其它传统类型的值具有相同的权利。函数可以存储到变量或者table中,可以作为实参传递给其他函数,还可以作为其它函数的返回值。“词法域”是指一个函数可以嵌套在另外一个函数中,内部的函数可以访问外部函数中的变量。
一个closure就是一个函数加上该函数所需访问的所有“非局部的变量”。
1 | function newCounter() |
上面这段代码中,匿名函数访问了一个“非局部变量”i,如果再次调用newCounter,那么它会创建一个新的局部变量i,从而也将得到一个新的closure。
可以使用同样的技术创建一个安全的运行环境,即所谓的“沙盒(sandbox)”。当执行一些未受信任的代码时就需要一个安全的执行环境,例如在服务器中执行那些从internet上接收到的代码。
1 | do |
经过重新定义后,一个程序就只能通过新的受限版本来调用原来那个未受限的open函数了。
表和面向对象
创建表
1 | t = {} |
设置和访问表内容,不存在的表内容返回nil
1 | t["key] = 1 |