$ sudo apt-get install lua5.2
$ brew install lua luarocks # luarocks是lua的模块管理工具 $ sudo ln -s /usr/bin/make /usr/bin/gmake # 解决 sh: gmake: command not found
$ luarocks install luasocket
$ lua
> socket = require("socket")
> print(socket._VERSION)
LuaSocket 2.0.2
$ luarocks install lua-cjson
$ lua
> cjson = require("cjson")
> print(cjson.encode({ name = "linguofeng" }))
{"name":"linguofeng"}
$ lua
> print("Hello World!!")
Hello World!!
print(type(nil)) -- 输出 nil
print(type(99.7+12*9)) -- 输出 number
print(type(true)) -- 输出 boolean
print(type("Hello Wikipedia")) -- 输出 string
print(type(print)) -- 输出 function
print(type{1, 2, test = "test"}) -- 输出 table
第一类值指:在Lua中函数和其他值(数值、字符串)一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值。
function add(x, y) -- 定义一个函数add,并接收两个参数
local a = x + y -- 定义一个局部变量a,接收x+y的和,局部变量仅在函数add中有效
return a -- 返回
end -- 结束add函数
print("15 + 64 = " .. add(15, 64)); -- 打印add(15, 64)的结果
local x = 1 -- local 关键字表示该变量为局部变量,作用域为当前上下文
-- 无该关键字修饰时为全局变量,作用于整个Lua状态机
local add = function(x, y) -- 局部函数,作用于当前脚本(chumk)
Lib = {}
Lib.add = function(x, y) -- 表函数,作用于Lib表
闭包是一个内部函数以及它的upvalues,内部函数使用了外部(父函数)局部变量。
function newCounter()
local i = 0 -- i为匿名函数的外部局部变量(upvalue)
return function() -- 匿名内部函数
i = i + 1 -- 使用了i,所以该匿名函数是一个闭包
return i
end
end
c1 = newCounter() -- 得到一个匿名函数的变量(闭包)
print(c1()) -- 调用匿名函数,打印出1
print(c1()) -- 调用匿名函数,打印出2
c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2
for int i = 0, 10, 2 do -- for循环,2表示步长,省略时为1
print("i = " .. i) -- .. 表示字符串连接符
end -- 结束for
if a > b then -- if条件判断语句
print("a > b")
else
print("b > a")
end
while a > b do -- while循环
print("")
end
repeat -- repeat-until循环
print("")
until a > b
逻辑运算符认为false和nil是假(false),其他为真,0也是true.
a and b -- 如果a为false,则返回a,否则返回b
a or b -- 如果a为true,则返回a,否则返回b
x = x or v -- 如果x为false或者nil时则给x赋初始值v
-- 等价于
if not x then
x = v
end
-- 三元运算符
a ? b : c => a and b or c -- and 的优先级别比 or 高
not -- not 的结果只返回false或true,作用类似于"非" "!"取反的意思
print(not nil) -- true
print(not false) -- true
print(not 0) -- false
co = coroutine.create(function () -- 创建一个协同函数,接收一个匿名函数,返回thread类型
print("hi")
end)
print(co) -- thread: 0x7fe1834127d0
print(coroutine.status(co)) -- 查看协同的状态,默认状态是挂起态 suspended coroutine.resume(co) -- 改变协同的状态为运行太 hi print(coroutine.status(co)) -- 协同运行完以后将变量停止态 dead
co = coroutine.create(function ()
print("hi")
coroutine.yield() -- 协同运行到此状态将变成挂起
print("你好")
end)
coroutine.resume(co) -- hi
coroutine.resume(co) -- 你好
coroutine.resume(co) -- false,协同结束后将不能再使用
co = coroutine.create(function (x, y) -- 接收两个参数
print("hi", coroutine.yield(x + y)) -- 返回一个值,同时参数也传递给了coroutine.yield
return 100 -- 第三种返回值的方式
end)
print(coroutine.resume(co, 12, 87)) -- 传递两个参数并接收返回值(true, 99)
-- 执行coroutine.yield(x + y)之前协同被挂起,但值被返回,因此print函数未被执行,下面执行
print(coroutine.resume(co, 12, 87)) -- 传递两个参数并接收返回值(true, 100)
arrays = {} -- 创建一个空表
arrays[1] = "abc" -- 第一个索引值为1
arrays[2] = 123
arrays["key"] = "value" -- map
for key, value in pairs(arrays) do -- 迭代table
print(key .. " = " .. value)
end
list = {123} -- 初始化表
list[2] = "abc" -- 增
list.x = 123
list.y = 987
list[1] = nil -- 删
list.y = nil
list[2] = 456 -- 改
list.x = 987
print(list[2]) -- 查
print(list.x)
print(list['x'])
list = {} -- 初始空化数组,数组的下标是整数,遵循Lua的标准,下标从1开始
list[1] = "abc"
list[2] = "edg"
list[3] = "hij"
mt = {} -- 创建矩阵matrix
for i = 1, N do -- 创建N行
mt[i] = {} -- 每行都是一个数组(table元素)
for j = 1, M do -- 创建M列
mt[i][j] = "a" -- 第N行第M行的值
end
end
![]()
list = nil
list = {next = list, value = "hello3"}
list = {next = list, value = "hello2"}
list = {next = list, value = "hello1"}
-- 遍历
local l = list
while l do
print(l.value)
l = l.next
end
元表也是普通表
t = {}
print(getmetatable(t)) -- 获取表的metatable nil,默认不带
mt = {}
setmetatable(t, mt) -- 设置一个元素
-- metamethod 元表的方法(元方法)
mt.__add -- 加 +
mt.__sub -- 减 -
mt.__mul -- 乘 *
mt.__div -- 除 /
mt.__unm -- 负 -
mt.__pow -- 幂 ^
mt.__concat -- 连接
mt.__eq -- 等于 =
mt.__lt -- 小于 <
mt.__le -- 大于 >
mt.__tostring -- print调用
mt.__metatable -- 设置该元表不被修改与访问
mt.__index -- 当访问不存在的元素时会去查询,相当于子类继承父类一样
mt.__newindex -- 更新表,如果增加一个不存在的元素,会去查询,有直接用,否则增加
记录下表的增查记录
local index = {} -- 私有的key,用来记录原始表在代理表中的下标
local mt = { -- 创建元表
__index = function(t, k)
print("访问了" .. tostring(k) .. "元素")
return t[index][k] -- 从代理表中获取原始表中k下标的数据
end,
__newindex = function(t, k, v)
print("更新了 " .. tostring(k) .. " 元素的值为 " .. tostring(v))
t[index][k] = v -- 更新代理表中下标为index的原始表中的元素
end
}
function setProxy(t)
local proxy = {} -- 创建代理表
proxy[index] = t -- 把原始表加到代理表的index下标中
setmetatable(proxy, mt) -- 设置代理表的元表
return proxy -- 返回代理表,即所有操作都是直接操作代理表
end
p = setProxy({})
p[2] = 'abcdefg' -- 更新了 2 元素的值为 abcdefg
print(p[2]) -- 访问了2元素
> _G["ewgegw"] = "ddddddgege" > table.foreach(_G, print) string table: 0x7ffce3407a60 xpcall function: 0x7ffce3404780 package table: 0x7ffce3405780 tostring function: 0x7ffce3405020 print function: 0x7ffce3405160 os table: 0x7ffce34073e0 unpack function: 0x7ffce34050d0 ewgegw ddddddgege -- 上面添加的全局变量 require function: 0x7ffce3405e70 getfenv function: 0x7ffce3404db0 setmetatable function: 0x7ffce3404f60 next function: 0x7ffce3404d20 assert function: 0x7ffce3404a80 tonumber function: 0x7ffce3404fc0 io table: 0x7ffce3406bd0 rawequal function: 0x7ffce34051b0 collectgarbage function: 0x7ffce3404ad0 getmetatable function: 0x7ffce3404e00 module function: 0x7ffce3405e20 rawset function: 0x7ffce3405260 math table: 0x7ffce3408290 debug table: 0x7ffce3408c50 pcall function: 0x7ffce3404d70 table table: 0x7ffce3405f10 newproxy function: 0x7ffce34052e0 type function: 0x7ffce3405080 coroutine table: 0x7ffce3405380 -- 对应的是协同的表 _G table: 0x7ffce3404110 select function: 0x7ffce3404ec0 gcinfo function: 0x7ffce3404150 pairs function: 0x7ffce34048c0 rawget function: 0x7ffce3405210 loadstring function: 0x7ffce3404cc0 ipairs function: 0x7ffce3404830 _VERSION Lua 5.1 dofile function: 0x7ffce3404bd0 setfenv function: 0x7ffce3404f10 load function: 0x7ffce3404c70 error function: 0x7ffce3404c20 loadfile function: 0x7ffce3404e60 > table.foreach(_G.os, print)
--pack.lua---------------------------------------------------------------------
local P = {}
-- 改变P表的__index,这里的_G代表全局环境
setmetatable(P, {__index = _G})
-- 改变当前的环境为P,setfenv前的所有定义都是在全局环境中进行的,后面的则都是在新环境中进行的,互不影响
setfenv(1, P)
-- 声明的add函数在环境P中,如果要在外部访问必须P.add
function add(x, y)
print(x .. ' + ' .. y .. ' = ' .. (x + y))
-- 由于当前新的环境中没有print函数,但是__index指向的是全局环境,所以print是全局的函数
end
return P
--pack1.lua--------------------------------------------------------------------
local P = {}
-- 如果需要改变环境后使用全局环境的方法需要记住,这种方法比上面的要快
local print = print
-- 改变当前的环境为P
setfenv(1, P)
-- 声明的add函数在环境P中,如果要在外部访问必须P.add
function add(x, y)
print(x .. ' + ' .. y .. ' = ' .. (x + y))
end
-- 私有方法
local function div(x, y)
end
return P
--main.lua---------------------------------------------------------------------
local p = require 'pack'
p.add(12, 34)
local p1 = require 'pack1'
p1.add(43, 19)
-- student.lua
student = {}
function student.sayHi()
print('Hello')
end
return student
-- 使用
student = require("student")
student.sayHi() -- Hello
local function _add(x, y) -- 私有局部函数
return x + y
end
utils = { -- utils包
add = _add -- 对外公开的函数
}
return utils
--Person.lua
local Person = {name = ''}
function Person:getName()
return self.name
end
function Person:setName(name)
self.name = name
end
function Person:new(object)
object = object or {}
setmetatable(object, {__index = self}) -- 元表 类似继承的意思
return object
end
return Person
--main.lua
-- 类
local Person = require 'Person'
-- 对象
local student = Person:new({age = 23})
student:setName('Tom')
print('name: ' .. student:getName() .. ' age: ' .. student.age)
实际就是记住所有父类,然后访问不存在的元素的时候去查询哪个父类中有,有就执行
local function search (k, plist)
for i=1, table.getn(plist) do
local v = plist[i][k] -- 去所有父类中获取
if v then return v end
end
end
function Person:new(...)
local o = {}
setmetatable(o, {__index = function (t, k)
local v = search(k, arg)
t[k] = v -- save for next access
return v
end})
return o
end
local function createAccount(_name) -- 工厂方法
local self = {name = _name}
local function _setName(name)
self.name = name
end
local function _getName()
return self.name
end
-- 公有方法表
local public = {
setName = _setName,
getName = _getName,
--name = self.name -- 不公开私有成员变量
}
return public
end
local account = createAccount('Tom')
print(account.name) -- 无法访问,因为没有公开
t = {name = 'table'} -- 创建一个普通表
setmatetable(t, {__made = 'k'}) -- k表示t表中的keys是weak的,v表示t表中的values是weak的
k = {} -- 创建一个空表,此时{}被k引用,引用值为1
t[k] = 1 -- 把空表作为key,由于t表的key是weak的,所以k值的引用如果为0则会被gc回收,如
k = {} -- 把k指向另一个新的{},则旧的{}引用值减1变成0了,目前t[k] = 1还有效
t[k] = 2 -- 把新的{}作为key,值是2
collectgarbage() -- 调用gc,清除引用为0的内存空间,此时,第一个{}的引用是0,会被gc掉,所以第一个t[k]以及值会被删除
for k, v in pairs(a) do print(v) end
-- 此时应该只剩下2了,因为第2个k = {}时改变了k指向新的{},而旧的{}引用会变成0,被gc掉
-------------------------------------------------------------------------
a = {};
setmetatable(a, {__mode = 'v'}); -- values为weak,当值的引用为0时,删除
v1 = {name = 'v1'}
v2 = {name = 'v2'}
a[1] = v1
a[2] = v2
v1 = v2
collectgarbage(); -- 调用GC,清掉weak表中没有引用的内存
for k, v in pairs(a) do print(v.name) end
-- 输出v2,因为v1重新指向{name = 'v2'},则{name = 'v1'}引用减1为0
-------------------------------------------------------------------------
a = {};
setmetatable(a, {__mode = 'kv'}); -- 同时检查kv,是上面两种情况的组合
v1 = {name = 'v1'}
v2 = {name = 'v2'}
v = {}
k = {}
a[1] = v
v = {} -- value重新引用新值,旧值被gc,如果旧值在table则对应的记录被清空
a[2] = v
a[k] = 1
k = {} -- key重新引用新值,旧值被gc,如果旧值在table则对应的记录被清空
a[k] = 2
collectgarbage(); -- 调用GC,清掉weak表中没有引用的内存
for k, v in pairs(a) do
print(v)
end
tables = {1, 2, 3, 4, 5, 6, 7}
print(#tables) -- 5.1开始使用#获取长度 -- 7
table.insert(tables, 8)
print(table.concat(tables)) -- 12345678
table.insert(tables, 1, 0)
print(table.concat(tables)) -- 012345678
print(table.maxn(tables)) -- 9
table.remove(tables)
print(table.concat(tables)) -- 01234567
table.remove(tables, 5)
print(table.concat(tables)) -- 0123567
print(table.concat(tables, ',')) -- 0,1,2,3,5,6,7
print(table.concat(tables, '-', 2)) -- 1-2-3-5-6-7
print(table.concat(tables, '=', 1, 4)) -- 0=1=2=3
table.sort(tables)
print(table.concat(tables)) -- 0123567
table.sort(tables, function(t1, t2)
if t1 > t2 then
return true
else
return false
end
end)
print(table.concat(tables)) -- 7653210
local file = io.open('tabletest.lua', 'r')
print(io.type(file))
for line in file:lines() do
--print(line)
end
--file:close()
io.close(file)
print(io.type(file))
------------------------------------------------------
for line in io.input('tabletest.lua'):lines() do
print(line)
end
for line in io.lines('tabletest.lua') do
--print(line)
end
table.foreach(os, print)
print(os.clock())
print(os.date())
print(os.date('%Y-%m-%d %H:%M'))
print(os.time())
print(os.difftime(1364957757, os.time()))
print(os.getenv ('PATH'))
print(os.tmpname ())
@压入@
table(table table-bordered). |_.函数|_.说明(栈底最后一个元素的索引是1,栈顶第一个元素是-1)| |lua_pushnil(lua_State*)|压入一个空值| |lua_pushboolean(lua_State*, int)|压入一个布尔值| |lua_pushcclosure(lua_State*, lua_CFunction, int)|压入一个C闭包?| |lua_pushcfunction(lua_State*, lua_CFunction)|压入一个C函数,由lua_pushcclosure(L, f, 0)宏定义出来| |lua_pushlightuserdata(lua_State*, void*)|压入一个指针,不被gc管理| |lua_pushinteger(lua_State*, lua_Integer)|压入一个数字| |lua_pushnumber(lua_State*, lua_Number)|压入数字| |lua_pushstring(lua_State*, const char*)|压入字符串| |lua_pushfstring(lua_State*, const char*, ...)|压入一个格式化的string| |lua_pushvfstring(lua_State*, const char*, va_list)|同上,只是接收一个va_list| |lua_pushlstring(lua_State*, const char*, size_t);|压入长字符串| |lua_pushliteral(lua_State*, const char*)|压入文字| |lua_pushthread(lua_State*)|压入一个线程?|@判断类型@
table(table table-bordered). |_.函数|_.说明| |lua_isboolean(lua_State*, int)|是否是布尔类型| |lua_iscfunction(lua_State*, int)|是否是C函数类型| |lua_isfunction(lua_State*, int)|是否是C函数或者Lua函数| |lua_islightuserdata(lua_State*, int)|是否是用户自定义类型指针| |lua_isnil(lua_State*, int)|是否是空| |lua_isnone(lua_State*, int)|是否是有效的| |lua_isnoneornil(lua_State*, int)|是否是上面两者| |lua_isnumber(lua_State*, int)|是否是数字| |lua_isstring(lua_State*, int)|是否是字符串| |lua_istable(lua_State*, int)|是否是table| |lua_isthread(lua_State*, int)|是否是线程| |lua_isuserdata(lua_State*, int)|是否是用户类型,包括full和light| |lua_type(lua_State*, int)|返回元素的类型,对应LUA_TNIL等枚举| |lua_typename(lua_State*, int)|返回元素的类型名称|@获取栈中的元素并转换成C类型@
table(table table-bordered). |_.函数|_.说明|_.返回值类型| |lua_toboolean(lua_State*, int)|把元素转换成C的布尔类型的值|int| |lua_tocfunction(lua_State*, int)|把元素转换成C的函数|lua_CFunction| |lua_tointeger (lua_State*, int)||lua_Integer| |lua_tolstring (lua_State*, int, size_t *len)||const char*| |lua_tonumber (lua_State*, int)||lua_Number| |lua_topointer (lua_State*, int)||const void*| |lua_tostring (lua_State*, int)||const char*| |lua_tothread (lua_State*, int)||lua_State| |lua_touserdata (lua_State*, int)||void*|@栈内元素的操作@
table(table table-bordered). |_.函数|_.说明|| |lua_gettop(lua_State*)|返回栈的元素个数,同时也是栈顶元素的索引| |lua_settop(lua_State*, int)|设置某个元素为栈顶元素,该元素之上的元素会被清除| |lua_pushvalue(lua_State*, int)|压入(拷贝)一个已经存在栈的元素至栈顶| |lua_insert(lua_State*, int)|移动栈顶元素至某个位置| |lua_remove(lua_State*, int)|删除栈中某个元素| |lua_replace(lua_State*, int)|替换栈顶元素至某个位置,相应那个位置的元素至栈顶|参考:http://book.luaer.cn
参考:http://www.lua.org/manual/5.1/manual.html