Lua 飞速入门
对 Rainmeter 有点兴趣,觉得可以作为我的画画时间的 dashboard。但我的逻辑明显需要一些数据处理,因此需要编程能力,而 RunCommand 不够方便,它的输出没法结构化,这时候使用它内嵌的 Lua 脚本是有必要的。所以,第一次地,我真的要去把 Lua 过一次了。上次想去接触 Lua,还是 Redis 有个滑动窗口的需求,当时是直接上 AI 了(因为这个算法明显会有些复杂)。
总之,记录我对 Lua 和 Rainmeter 的学习,实践优先,理解优先,按照我最喜欢的学习方式去学习。先把 Lua 过一遍。
Lua 我用 Rainmeter 的嵌入式环境,我就不自己下环境了,找个 在线解释器 去测试代码和语法。
Lua 入门
Lua 是一门(假装自己)面向对象的,动态类型的解释型语言,对空值非常松散(最典型的例子是,任何变量标识符都认为是合法变量但返回 nil,这让拼写错误非常致命。保持警惕!它比没有”use strict”的 js 还松散,得当成 perl 那类看待),语法类似 ruby。
lua 没有 try-catch 式的异常处理,它的异常处理是类似函数式的(感觉有点像 haskell),这里我不提及。lua 的协程我也不去学习。
Lua 有基于原型的 OOP,但我不学习。基于闭包的封装足够我用了。
lua 使用下划线命名法……但 tmd,Rainmeter 的 API 是大驼峰……我……我入乡随俗用下划线命名好了?
数据类型
Lua 有 nil,number,string,table,boolean,function(一等公民),userdata(C 扩展)……
- number 类型同 js——双精度浮点数,其中 53 位保存整数
- Lua 只有一个容器类型——table,数组和哈希表均是它(这其实也像 js?)。
- boolean 字面量是 true 和 false,取反是 not;and,or 语义和 python 相同,不等于是
~=。 - 空值是 nil(未初始化的变量也是它;没有 js 一样的 undefined)
- 只有 nil 和 false 是假值,其它均为真(空 table 也是真(不过对这样一个我不能算熟悉的语言,我不会利用这种太需要记忆的特性啦))
- 字符串使用单引号或双引号均可
- 关于字符串和数字操作——
- 使用
+-*/等去操作数字 - 使用
..去连接字符串 - 使用
#去获取字符串长度(#'hello' == 5) - 使用
..操作数字时,会把数字当作字符串操作,得到字符串;使用+-*/等操作字符串时,会把字符串当作数字操作,得到数字 - 转换失败会报错(异常),使用 tonumber,tostring 函数进行显式转换,转换失败返回 nil
- 检查操作符不允许字符串和数字互操作,除了
==和~=,而数字和字符串总是不相等的,10 ~= '10'。
- 使用
语句
for 中可以 break,但不能 continue。lua 同样提供了 goto,但我不提它。
1 | |
注释,作用域
1 | |
函数和函数调用
函数是一等公民。函数调用不检查参数匹配。
多个返回值
lua 没有 tuple,但允许函数返回多个值,并使用多个变量去接受这个函数的返回值,无法使用一个变量捕获所有返回值,除非使用 table。就这个行为来看,lua 似乎倾向“展开”函数的多个返回值,但有反例去反驳这个理解——a, b, c = f(), 3,如果以展开理解应该是得到1, 2, 3,结果得到的是1, 3, nil。我的建议是——不要这么写。
1 | |
table
Lua 的 table 花活儿繁多,lua 使用 table 去实现数组和映射表,实际上,Lua 的模块就是 table。这里先讨论 table 作为 table 的部分,再讨论 table 用于封装的部分。
初始化
关于 table 的字面量:
1 | |
方法
Lua 中,table 自己没有方法,都是使用 table 库函数去操作的,就像 js 的 object。
我既然在脑子里还是想要区分一个 table 究竟是数组还是映射表,我就该在方法上也作出区分。
数组操作
table.insert(table, [pos,] value):在特定位置后插入(否则在末尾插入)table.remove(table, [pos]):移除特定位置#t:长度table.unpack(table):解构,使用多个变量接受数组中的所有值table.sort(table, [comp]):排序,可传入比较器函数table.concat(table, [sep, [i, [j]]]):join 操作,i 和 j 是要进行 join 的那部分数组的下标范围,闭区间
没有切片操作,需要自己实现
映射表操作
next(t) == nil:判空t[k] = nil:删除键
映射表长度必须用 pairs 遍历计数。
关于成员和调用
下面展示成员定义和访问,以及方法调用上的花活儿。Lua 像 js 一样,. 和 [] 均可访问成员,但不像 python——没有什么描述符协议,这使得绑定方法时不会自动绑定 self。
注意这个:,明显是为了方便面向对象编写才提供的,使用该语法编写函数时,自动添加 self 作为第一个参数以让它成为方法;使用该语法调用方法时,自动使用调用者作为第一个参数。
1 | |
You guess what?我就学这些。毕竟我用 lua 是只把它当作 Rainmeter 和我的 python 脚本的胶水去用。如果有字符串和日期处理的需求,我再专门去学就是了。它不是 Python,我不会把它当成我的主力。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 协议 ,转载请注明出处!