## 此为阅读<Programming in lua>学习笔记
Chapter 1 Hello
- hello world
print("hello world")
- function
function fact(n) if n == 0 then return 1 else return n * fact(n - 1) end end a = io.read() print(fact(a))
文件存为 hello.lua
- run (& load library)
lua > dofile("hello.lua") -- 导入 hello.lua包(load your library),类似python的import > print fact(10)
- 访问未初始化的变量不会保存, lua变量有两种状态 nil 非nil (即存在/不存在)
- 作用域 非local变量都为全局变量
Chapter 2 types & values
- lua 是动态语言, 不需要定义类型 且 lua一切都是变量
- 基本类型 nil, boolean, number, string, userdata, function, thread, table >>> 函数 type可以测试类型
- nil 说明 一个全局变量未赋值前为 nil ,且给一个变量赋 nil >>> 删除该变量
- boolean ***只有false和nil为假, 其他都为真(包括0和空串)***
- number >>>实数(数字)
- string >>> 字符串不可变性. [[ some strings ]] >>>类似python的 """some string""" ***当一个字符串使用算术运算符, 其自动转换为数字类型. 相反 期望字符串的地方出现数字,数字自动转换为字符串*** 字符串连接符为 .. (双点号, 连接两边必须加空格)
- 标准库 string库, table库, I/O库, OS库, 算术库, debug库
Chapter 3 Expression
- 算术 二元:+-*/^(加减乘除幂) 一元:-(负)
- 运算 < > <= >= == ~= *** ==当且仅当同一对象为真, ~=当值相等(但不是同一对象)为真 eg. a = {};a.x = 1 b = {};b.x = 1 a == b -->false, a ~= b -->true .而且,a ~= a -->false***
- 逻辑 and or not -->类似python 不同的是lua把0和空串都当真,有些运算结果和python不同, lua: (a and b) or c -->c语言的 a ? b : c . 小技巧 x = x or v (当x为nil时给x赋值为v)
- 串连接 .. (双点号)(左右一定要加空格)
- 除了^和..外所有的二元运算符都是左连接的。
- 表 1.lua表(数组下标从1开始) 2.lua表元素可以是任何元素 3.lua表元素可以是 .属性 方式创建和访问(属性不参与下标计数),可以下标访问(当然了,怎么创建就怎么访问) 4每次调用构造函数(即{}),都生成一个table
-- 生成一个链表 <linked_list.lua> ctrl + d结束i/o输入 list = nil for line in io.lines() do list = {next=list, value=line} end l = list print(l) while l do print(l.value) l = l.next end -- 手动修改table下标,使其下标从0开始,不推荐下标从0开始(因为和标准库不兼容) days = {[0]="Sunday", "Monday", "Tuesday"}
- table可以用逗号(,)和分号(;)分割,通常用;分割不同类型元素
Chapter 4 Statements
- 赋值语言 和python类似, 特别的a, b = a+1, b+1, b+2 -- value of b+2 is ignored
- 显示划分代码块(block)使用do - end (类似c的{}内的部分), 块内是局部变量
do local a = 2 -- do something end -- scope of 'a' ends here print(a) -- result: nil
- 控制循环
-- condition and cycle -- if oo then xx elseif oo then xx else xx end oo is condition, xx is action a = a or 3 if a > 3 then -- do someting print(a) elseif a == 3 or a ~= 3 then -- do someting print(a) else -- do something print(a) end -- 块结束,end不可少 -- while oo do xx end while a > 0 do print(a) a = a - 1 -- 不支持 a++, ++a, a += 1(a += 1 python支持) end -- repeat xx until oo 类似c的do - while repeat print(a) until a == 3 -- for oo1, oo2, (oo3) do xx end oo3是步长,默认是1 for i=0, 3 do -- *** 包含oo2,相当于 <= , 和c/python(左闭右开)风格不同 *** 且表达式oo1,oo2,oo3只计算一次(在循环前) print(i) end -- for oo in oos 遍历迭代子函数 for key, value in ipairs({["a"]=2,4,5}) do -- ipairs -> build-in function 迭代table中的数组部分 print(key, value) -- pairs -> 迭代整个table元素包括数组部分和非数组部分(数组部分:下标是数字并且不是0,非数组部分下标是串/record风格/0) end -- io.lines -> 迭代文件每行 -- string.gmatch -> 迭代字符串单词
Chapter 5 Function
- lua的实参和形参的匹配和赋值类似:多余的部分被忽略,缺少的部分用nil补足
-- prototype function f(a, b) return a or b end -- call f(3) -- a = 3, b = nil f(3, 4) -- a = 3, b = 4 f(3, 4, 5) -- a = 3, b = 4, (5 is discarded)
- 可以返回多个结果值(和python返回tuple类似)
-- prototype function f() return a, b end -- call m = f() -- m = a m, n = f() -- m = a, n = b m, n, q = f() -- m = a, n = b, q = nil
- 一个特殊函数unpack, 接受数组作为输入参数, 返回数组所有元素(貌似python不需要这样的函数, 接受迭代器就行了)
fp = string.find -- 函数指针 a = {"hello", "ll"} print(fp(unpack(a))) -- > 3 4
- 可变参数, 和c类似, 用arg表存放可变参数, arg有一个域n表示参数个数(仅可变参数的个数), unpack arg是个好主意
-- prototype function f(a, b, ...) end -- call f(3) -- a = 3, b = nil , arg = {n=0} f(3, 4) -- a = 3, b = 4, arg = {n=0} f(3, 4, 5, 6) -- a = 3, b = 4, arg = {5, 6; n=2}
- 虚变量 用下滑线_表示, 一般不想要前面的返回值,使用它起着占位的作用 eg local _, x = string.find("hello", "ll") -- x = 4
Chapter 6 More About Functions
- Lua函数是带有词法定界(lexical scoping)的第一类值(first-class values).
- 既然函数是值,那么创建函数其实可以:
-- function foo(x) return x ^ 2 end 形式其实是语法甜头 -- 这个是真正的形式 foo = function (x) return x ^ 2 -- python的幂是 ** (c ^表示异或) end --
- 高阶函数
-- 类似python的 sorted (stl 的sort algorithm) users = { {name="zhangsan", score=90}, {name="lisi", score=88}, } table.sort(users, function (a, b) return (a.name > b.name) end) -- 通过表的name域排序
- 闭包 当一个函数内部嵌套另一个函数定义时, 内部的函数体可以访问外部的局部变量(***upvalue), 这种特征称作词法定界 ***upvalue:
function newCounter() local i = 0 -- upvalue return function() -- anonymous function i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2
- 闭包 重定义函数
-- 可以重新包装函数, 实现新功能 -- 重定义sin函数, 使其接受角度而不是弧度 math.sin = function(x) return math.sin(x * math.pi / 180) -- x is upvalue end
- 闭包 重定义函数2
-- 可以重新包装函数, 实现新功能 -- 重定义sin函数, 使其接受角度而不是弧度 do local oldSin = math.sin math.sin = function(x) --*1 return oldSin(x * math.pi / 180) end end -- do -- end 代码块:由于oldSin是局部变量, 而新定义的math.sin(*1行)是全局的,所以只可以用新版本的math.sin函数 把不安全代码函数重定义并发在局部代码块类, 类似于沙箱
- 非全局函数
-- 函数作为table的域 (方式1) Lib = {} Lib.add = function (x, y) return x + y end Lib.sub = function (x, y) return x - y end -- 函数作为table的域 (方式2) Lib = { add = function (x, y) return x + y end, sub = function (x, y) return x - y end, } -- 函数作为table的域 (方式3) Lib = {} function Lib.add(x, y) return x + y end -- ... -- 定义局部函数(函数就是变量) local f = function (x, y) return x + y end -- 或者 local function f(x, y) return x + y end -- 局部函数前向申明(当是递归时, 内部并不知道自己是局部函数, 还会去全局查找, 找不到还好, 万一找到了就不好了,哈哈) local fact -- *1 fact = function (n) if n == 0 then return 1 else return n*fact(n-1) -- 如果没有 *1 它就去全局查找fact了 end end -- 迷宫游戏(状态机), 从room1开始,走到room4 function room1() local move = io.read() if move = "S" then return room3() elseif move = "E" then return room2() else print("invalid move") return room1() -- stay the same room end end function room2() local move = io.read() if move = "S" then return room4() elseif move = "W" then return room1() else print("invalid move") return room2() -- stay the same room end end function room3() local move = io.read() if move = "N" then return room1() elseif move = "E" then return room4() else print("invalid move") return room3() -- stay the same room end end function room4() print("you go out the maze") end
- ing