Programming in Lua 笔记

变量

  1. 全局变量直接使用的时候为nil
  2. 数组下标从0开始(不推荐)a = {[0]="123","32","23"};
  3. 支持多返回值,多个同时赋值,只需要一个时候使用哑元_
  4. 尽量避免一个下划线开头+大写字母
  5. ---[[可以注销掉块注释
  6. type函数永远返回一个字符串
  7. lua将falsenil视为假,将0和空字符串视为真
  8. LUA对于小于1014的数字用双精度没有四舍五入的浮点误差,合法的数字写法:4,0.4,4.58e-3,0.3e12,5e+20
  9. Lua的字符串是只读的,\<ddd>表达数值转义,[[ ]],[===[ ]===]界定换行字符串,(类似的界定注释)
  10. tonumber, tostring不成功返回nil
  11. #a获取字符串a的长度,table.maxn对于nil更加安全
  12. table永远是匿名的,a ={},b=ab保持了一个对于a所指向table的引用
  13. a.xa["x"]是一样的,点作为记录,key暗示任意字符串
  14. x - x%1取整
  15. x,y=y,x交换
  16. do end构成基本块(local)

I/O

a = io.read("*number")
print(a)

function

notes

  1. 如果要在函数中间使用return,需要加do return end
  2. 可变参数(...), 获取arg
  3. 尾调用不保留调用者栈,这种情况下不会栈溢出, goto(用来编写状态机)
  4. 若将函数返回值作为不是最后一个的表达式,保留第一个返回值
  5. 如果函数调用在单独的一个圆括号里面,只能返回一个结果
  6. 函数名只是持有某个函数的变量
  7. 函数内部变量是一个closure,相当于对象的private variable

example

function foo(x) return 2 * x end
==
foo = function (x) return 2 * x end


--
function derivative(f, delta)
    delta = delta or 1e-4
    return function(x)
        return (f(x+delta) - f(x))/delta
    end
end

sort

table.sort(tb, function(a,b) return (a.name > b.name) end

3-var

-- 对于and来说第一个操作数为真,返回第二个操作数
-- or第一个操作数为假,返回第二个操作数
(a and b) or c  -- a ? b : c, b不可以为false

unnamed

foo = function(x) return 2 * x end

递归

需要先定义局部变量

local fact -- 这一句和下一句要求分开【bug主要在这里】
fact = function(n)
if n == 0 then return 1
else return n * fact(n-1)
end
end

or

local function fact(n)
    if n==0 then return 1
    else return n * fact(n-1)
    end
end

闭包

内部的函数体可以访问外部函数的局部变量(upvalue)

domo 重定义限制程序打开文件

do
    local oldOpen = io.open
    io.open = function(filename, mode)
        if access_OK(filename, mode) then
            return oldOpen(filename, mode)
        else
            return nil, "access denied"
        end
    end
end

局部函数

-- g can use f here
local f = function(...)
end
local g = function(...)
f()
end

递归局部函数

需要先声明

local fact
fact = function(n)
    if n == 0 then
        return 1
    else
        return n * fact(n-1)
    end
end

tables

a = {}; a.x = 1;
b = {}; b.x = 1;
a ~= b

a.foo = function(x,y) return x + y end
unpack(a)-- 分离一层

block

normal

do
    local i = 1
end
do return end -- 用于调试

if, while, repeat

if conditions then
elseif conditions then
end

while condition do
end

repeat
    statements;
until conditions;

for

for var = beg,end,step do -- 如果为表达式一次性求职
end

for i,v in ipairs(a)
do
end

for key in pairs(v)
do
end

-- 死循环
for i = 1,math.huge do
end

iterator

  1. 使用闭包实现
function list_iter(t)
    local i = 0
    local n = table.getn(t)
    return function()
        i = i + 1
        if i <= n then return t[i] end
    end
end

t = {1,2,3}
iter = list_iter(t)
while true do
    local element = iter()
    if element == nil then break end
    print(element)
  1. 范性for本身实现for <var-list> in <exp-list> do end
  2. 无状态的迭代器for i,v in ipairs(a) do end

编译运行

  1. require 会搜索目录加载文件,避免同一个文件
  2. load c
    lua
    local path = "/xxxx/xxx.so"
    loacl f= loadlib(path, "luaopen_socket")

错误

抛出

if n then error("123") end
assert(io.read("*number"), "123")

处理

function foo()
    error()
end

if pcall(foo) then
    -- no error
else
    -- error
    print(debug.traceback())
    -- or next way
    local status, err = pcall(xxx):
    print(err)
end

协同程序

Lua将所有关于协同程序的函数放置在一个名为coroutine的table里面

fco = coroutine.create(f) -- 创建,处于挂起状态
coroutine.resume(fco) -- 启动或者再次启动
coroutine.status(co) -- suspended/running/dead/normal

coroutine.yield() -- 函数内部挂起,yield(1,2)将返回1,2

非抢占式多线程
管道,迭代器

co = coroutine.create(func)
-- print(co)
-- print(coroutine.status(co)) 
-- suspended(创建成功,yeild), running, dead
-- coroutine.resume(co)
-- coroutine.yield()
  1. 第一,加载 LuaSocket 库
    require “luasocket”
  2. 第二,定义远程主机和需要下载的文件名
    host = “www.w3.org”
    file = “/TR/REC-html32.html”
  3. 第三,打开一个 TCP 连接到远程主机的 80 端口(http 服务的标准端口)
    c = assert(socket.connect(host, 80))
    上面这句返回一个连接对象,我们可以使用这个连接对象请求发送文件
    c:send(“GET ” .. file .. ” HTTP/1.0\r\n\r\n”)
    receive 函数返回他送接收到的数据加上一个表示操作状态的字符串。当主机断开连接时,我们退出循环。
  4. 第四,关闭连接
    c:close()

自定义table参数

-- t.__tostring = xxx
-- set:
local mt = { __index = t}
setmetatable(proxy, mt) 

__tostring -- 打印
__index -- t[x] getter
__newindex -- t[x] setter

全局变量

_G[x]

局部作用域

-- 创建
a = 1  -- create a global variable 
-- change current environment 
setfenv(1, {_G = _G}) 
_G.print(a)    --> nil 
_G.print(_G.a)  --> 1
-- 继承
a = 1 
local newgt = {}    -- create new environment 
setmetatable(newgt, {__index = _G}) 
setfenv(1, newgt)   -- set it 
print(a)        --> 1 

面向对象

function Account:withdraw(v) -- a:withdraw
function withdraw(self, v) -- a.withdraw(可以互相通用)
  1. 原表中实现类的方法,算术方法包括:__add,__mul,__sub,__div,__unm,__mod,__pow,关系方法包括__eq,__lt,__le
  2. 表中找不到会访问__index(t,k)方法,更新为__newindex(t,k,v)方法

    function setDefault(t,d)
        local mt = {__index=function() return d end}
        setmetatable(t,mt)
    end
    
    local key = {} -- trick, 唯一索引
    local mt = {__index = function(t) return t[key] end}
    fuction setDefault(t,d)
        t[key] = d
        setmetatable(t,mt)
    end
  3. 新建对象
    lua
    function c:new(o)
    o = o or {}
    setmetatable(o,c)
    return o
    end

继承

SpecialAccount = Account:new()
s = SpecialAccount:new{limit=1000.00}
-- 多重继承
function createClass(...)
    local c = {}
    setmetatable(c, {__index=function(t,k) return search(k,arg) end })
end

weak表

  • 如果将一些对象放到一个数组当中,Lua将不会回收他们
  • 如果一个对象只有弱引用指向它,那么gc会自动回收该对象的内存。
  • weak 表
    一个weak引用 阻止 对象被回收,表的weak性由他的metatable__mode域来制定的,kkeyweak,vvalueweak
a, b = {}, {}
setmetatable(a,b)
b.__mode = \"k\"

collectgarbage()

用途: 记忆函数,对象的属性关联

函数工厂

function newzxx(xxx):
    local f = functionxx
    return {f=f}
end

解析

setfenv(f, table):设置一个函数的环境
  (1)当第一个参数为一个函数时,表示设置该函数的环境
  (2)当第一个参数为一个数字时,为1代表当前函数,2代表调用自己的函数,3代表调用自己的函数的函数,以此类推

标准库

数学

简介

数学库由算术函数的标准集合组成,比如三角函数库(sin, cos, tan, asin, acos, etc.),
幂指函数(exp, log, log10),舍入函数(floor, ceil)、max、min,加上一个变量 pi。数学
库也定义了一个幂操作符(^)。
所有的三角函数都在弧度单位下工作。(Lua4.0 以前在度数下工作。)你可以使用 deg
和 rad 函数在度和弧度之间转换。

random

math.random 用来产生伪随机数,有三种调用方式:
+ 第一:不带参数,将产生 [0,1)范围内的随机数.
+ 第二:带一个参数 n,将产生 1 <= x <= n 范围内的随机数 x.
+ 第三:带两个参数 a 和 b,将产生 a <= x <= b 范围内的随机数 x.
math.randomseed(os.time())

table

lua 假定array在最后一个非nil位置结束

table.getn -- memory search
table.setn
table.insert(a,x) -- push
table.remove(a) -- pop
table.insert(a,1,x), table.remove(a,1)
table.sort

string

string.len(s)
string.rep(s,n) -- repeat s for n times
string.lower(s) -- upper
string.sub(s,i,j) -- begin with 1. end as -1
i, j = string.find(s, "hello", [beg pos])
s, count = string.gsub(ori, mod, replace[, time])

IO

简单模式/完全模式

io.input(filename), io.output(filename)
io.read() -- a line
io.read(*all)
io.read(*number)
io.read(*line)
io.read(*num) --  char num
io.read(0) -- whether EOF
io.write("",math.sin(3),"")

f = assert(io.open("xxx.xxx", "r"))
local lines, rest = f:read(BUFISIZE,"*line")
outf:flush

os

os.time(year=x, month=x, day=x)
<-->
os.date("*t",1233)

debug

  1. 栈级别
  2. HOOK(call, return, line, count)

useful functions

string.format(fmt.."%q", unpack(arg), "1234")
table.sort(tb1, function(a,b) return (a.name>b.name) end)
io.read(*all)
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页