1 -- 单行注释
2 --[[
3 [多行注释]
4 --]]
5
6 ----------
7 - 1. 变量 & 控制流
8 ----------
9 num = 23 -- 数字都是双精度
10 str = 'aspythonstring' -- 像 Python 一样不可变
11 str = "aspythonuse" -- 可以双引号
12 str = [[
13 像 Python 的多行注释可用于
14 表示多行字符串一样
15 方便
16 ]]
17
18 bol = nil -- 未定义;支持垃圾回收
19
20 -- 缩进只为易读性,像 Matlab 一样以 end 结尾
21 while num < 50 do
22 num = num + 1 -- 没有 ++ 或 += 自增操作符号
23 end
24
25 -- IF 条件开关
26 if num > 40 then
27 print('> 40')
28 elseif s ~= 'aspython' then -- ~= 表示 !=
29 io.write('s is not aspython') -- 风骚的标准输出
30 else
31 thisIsGlobal = 5 -- 驼峰式命名
32 -- 显示声明局部变量(像 Javascript 一样)
33 local line = io.read()
34
35 -- .. 作为字符串连接符
36 print('凛冬将至' .. line)
37 end
38
39 -- 引用未定义变量将返回 nil ,这不是错误
40 foo = anUnknownVariable -- 等价于 foo = nil
41
42 aBoolValue = false
43 -- 只有 nil 与 false 为逻辑假; 数字 0 与空字串 '' 为真!
44 if not aBoolValue then print('false') end
45
46 -- 像 Python 一样运用 'or' 和 'and'
47 -- 得到 C 语言中 a ? b : c 的效果;需注意 b = false 或 nil 的情况
48 ans = aBoolValue and 'yes' or 'no'
49
50 karlSum = 0
51 for i = 1, 100 do -- 像 Matlab 一样的递增语法,包括两端,如同数学中[1, 100]
52 karlSum = karlSum + i
53 end
54
55 -- Step 为 2 递减的方式 '100, 1, -2'
56 for j = 100, 1, -2 then print(j) end
57
58 -- 综上,范围可表示为 "begin, end [, step]"
59
60 -- 另一个循环控制
61 num = 23
62 repeat
63 print('凡人必有一死')
64 num = num - 1
65 until num == 0
66
67
68 ----------
69 - 2. 函数
70 ----------
71 function fib(n)
72 if n < 2 then return 1 end
73 return fib(n - 2) + fib(n - 1)
74 end
75
76 -- Javascript 一样的匿名函数与闭包
77 function adder(x)
78 -- 返回一个函数
79 -- 闭包内封存 x 值
80 return function (y) return x + y end
81 end
82 a1 = adder(9)
83 a2 = adder(36)
84 print(a1(16)) --> 25
85 print(a2(64)) --> 100
86
87 -- 遇到不匹配的列表长度时
88 -- 过长的变量将被赋予 nil
89 -- 过长的值将被忽略
90
91 x, y, z = 1, 2, 3, 4 -- 4 将被忽略
92 function bar(a, b, c)
93 print(a, b, c)
94 return 4, 8, 15, 16, 23, 42
95 end
96 x, y = bar('zaphod') --> "zaphod nil nil"
97 -- x = 4, y = 8, 其余值被忽略
98
99 -- 函数与其他类型一样为一等公民
100 -- 同样有 local/global 之分
101 -- 像 Javascript 一样定义
102 function f(x) return x * x end
103 f = function (x) return x * x end
104
105 print 'Hello World!' -- 只有一个`字符串`参数时可省略括号
106
107 ----------
108 - 3. 表(Table)
109 ----------
110 -- 表是 Lua 中唯一的复合类型
111 -- 像 PHP 中的数组或 Javascript 中的 Object 一样
112 -- 可用作 list/dict/map
113
114 -- 默认以字符串作为 key
115 t = {key1 = 'value1', key2 = false}
116 -- 像 Javascript 一样以 . 取值
117 print(t.key1) --> "value1"
118 t.key3 = {} -- 加入新的键值对
119 t.key2 = nil -- 销毁一组键值对
120
121 -- 理论上任何非 nil 的变量都可以作为 key
122 u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
123 print(u[6.28]) --> "tau"
124 a = u['@!#'] -- a = 'qbert'
125 b = u[{}] -- b = nil;像 Javascript 一样 {} 会创建新的对象
126 -- 因此不要用蛋疼的 key 值,老老实实用字串或数字
127
128 -- 同字符串一样,只有一个表作为函数的参数时可以省略括号
129 -- 为了一个括号增加阅读难度,得不偿失
130 function h(x) print(x.key1) end
131 h{key1 = 'Sonmi~451'} --> "Sonmi~451"
132
133 for key, val in pairs(u) do -- 像 Python 一样的键值迭代
134 print(key, val)
135 end
136
137 -- 像 Javascript 一样的全局作用域 _G
138 print(_G['_G'] == _G) --> true
139
140 -- 省略 key 之后即可变身为 list
141 -- 实际上是以递增自然数为 key
142 v = {'value1', 'value2', 1.21, 'gigawatts'}
143 for i = 1, #v do -- 像 Bash 一样,#v 表示列表长度
144 print(v[i]) -- 像 Matlab 一样,列表索引从 1 开始
145 end
146
147 ----------
148 - 3.1 Metatables & metamethods
149 ----------
150 -- 元表(metatable)就是表的表,像 Javascript 的原型(prototype)一样
151 -- 为表重载一些元方法(metamethods)
152
153 f1 = {a = 1, b = 2}
154 f2 = {a = 2, b = 3}
155 -- s = f1 + f2 为错
156
157 mm = {}
158 function mm.__add(x, y)
159 sum = {}
160 sum.a = x.a + y.a
161 sum.b = x.b + y.b
162 return sum
163 end
164
165 setmetatable(f1, mm)
166 setmetatable(f2, mm)
167
168 -- 实际调用 f1 的 metatable 中的 __add(f1, f2)
169 -- 只为 f1 设置元表也可以
170 s = f1 + f2 -- s = {a = 3, b = 5}
171
172 -- s2 = s + s 为错,s 未定义元表
173
174 -- __index 元方法重载表中 key 的提取符号 `.`
175 defaultFavs = {animal = 'gru', food = 'donuts'}
176 myFavs = {food = 'pizza'}
177 setmetatable(myFavs, {__index = defaultFavs})
178 food = myFavs.food
179
180 -- Lua 中的值都具有元方法,只有 Table 可以重载
181 -- 所有元方法如下
182
183 -- __add(a, b) for a + b
184 -- __sub(a, b) for a - b
185 -- __mul(a, b) for a * b
186 -- __div(a, b) for a / b
187 -- __mod(a, b) for a % b
188 -- __pow(a, b) for a ^ b
189 -- __unm(a) for -a
190 -- __concat(a, b) for a .. b
191 -- __len(a) for #a
192 -- __eq(a, b) for a == b
193 -- __lt(a, b) for a < b
194 -- __le(a, b) for a <= b
195 -- __index(a, b) <fn or a table> for a.b
196 -- __newindex(a, b, c) for a.b = c
197 -- __call(a, ...) for a(...)
198
199 ----------
200 - 3.2 类风格的 Table 与继承
201 ----------
202
203 -- 像 Javascript 一样并没有内置 Class
204 -- 但可以通过 Table `{}` 实现
205
206 Dog = {} -- 1.
207 function Dog:new() -- 2.
208 newObj = {sound = 'woof'} -- 3.
209 self.__index = self -- 4.
210 return setmetatable(newObj, self) -- 5.
211 end
212 function Dog:makeSound() -- 6.
213 print('I say ' .. self.sound)
214 end
215
216 mrDog = Dog:new() -- 7.
217 mrDog:makeSound() --> "I say woof"
218
219 -- 1. Dog 像类但实际是 Table
220 -- 2. Dog:new(...) := Dog.new(self, ...)
221 -- 3. newObj 作 Dog 的实例
222 -- 4. self 是 Lua 中默认的参数,在这里 self = Dog
223 -- 继承的时候可以改变
224 -- self.__index 与 self 的元方法 __index 不是一回事
225 -- self = {__index = self, metatable = {__index = ...}}
226 -- 5. setmetatable(newObj, self) 相当于 setmetatable(newObj, {__index = self})
227 -- 赋予实例所有类方法
228 -- 6. 同 2.
229 -- 7. mrDog = Dog.new(Dog)
230
231 -- 继承
232 LoudDog = Dog:new()
233 function LoudDog:makeSound()
234 s = self.sound .. ' '
235 print(s .. s .. s)
236 end
237 seymour = LoudDog:new()
238 seymour:makeSound() --> "woof woof woof"
239
240 ----------
241 - 4. 模块
242 ----------
243
244 -- 以下来自文件 mod.lua
245 local M = {}
246
247 local function sayMyName()
248 print('Hrunkner')
249 end
250
251 function M.sayHello()
252 print('Why hello there')
253 sayMyName()
254 end
255 return M
256 -- 以上
257 -- 回到主文件
258 local mod = require('mod') -- 运行 mod.lua 中的代码
259 -- 操作同下
260 local mod = (function()
261 -- 像 Javascript 一样
262 --[[
263 mod.lua 中的代码
264 ]]--
265 end)()
266
267 mod.sayHello() --> "Why hello there"
268 mod.sayMyName() --> 错!sayMyName() 是 mod.lua 中的局部变量
269
270 -- require 返回的值将被缓存
271 -- 即使多次调用 require 被调用文件也只运行一次
272
273 -- mod2.lua 包含 print("mod2")
274 local a = require("mod2") --> "mod2"
275 local b = require("mod2") -- 不输出, 实际为 b = a
276
277 -- dofile 是不缓存的版本的 require
278 dofile("mod2") --> "mod2"
279 dofile("mod2") --> "mod2"
280
281 -- loadfile 读取文件但不执行
282 -- 勘误:f = loadfile('mod2'),需加后缀名,否则找不到文件
283 f = loadfile('mod2.lua')
284 f() --> "mod2"
285
286 -- loadstring 读取代码字符串
287 f = loadstring("print('Lua is cool!')")
288 f() --> "Lua is cool!"
289
290 ----------
291 - 5. 参考,略
292 ----------
















