生活随笔
收集整理的這篇文章主要介紹了
Lua-简洁、轻量、可扩展的脚本语言
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自:http://rmingwang.com/The-Programming-Language-Lua.html
?
1. 一、Lua安裝及常用庫的安裝
2. 1.1 Ubuntu
$ sudo apt-get install lua5.23. 1.2 OS X
$ brew install lua luarocks # luarocks是lua的模塊管理工具$ sudo ln -s /usr/bin/make /usr/bin/gmake # 解決 sh: gmake: command not found4. 1.3 luasocket庫的安裝
$ luarocks install luasocket$ lua> socket = require("socket")> print(socket._VERSION)LuaSocket 2.0.25. 1.4 lua-cjson庫的安裝
$ luarocks install lua-cjson$ lua> cjson = require("cjson")> print(cjson.encode({ name = "linguofeng" })){"name":"linguofeng"}6. 二、HelloWorld
$ lua> print("Hello World!!")Hello World!!7. 三、數據類型 有8種基本數據類型
類型 說明nil 全局變量默認值,如果要刪除一個全局變量可以賦值為nilboolean 布爾值number 數字型string 字符串型userdata 用戶自定義類型,一般是C/C++中的類型function 函數thread 線程table 表print(type(nil)) -- 輸出 nilprint(type(99.7+12*9)) -- 輸出 numberprint(type(true)) -- 輸出 booleanprint(type("Hello Wikipedia")) -- 輸出 stringprint(type(print)) -- 輸出 functionprint(type{1, 2, test = "test"}) -- 輸出 table8. 四、函數 第一類值
第一類值指:在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表9. 函數閉包
閉包是一個內部函數以及它的upvalues,內部函數使用了外部(父函數)局部變量。
function newCounter() local i = 0 -- i為匿名函數的外部局部變量(upvalue) return function() -- 匿名內部函數 i = i + 1 -- 使用了i,所以該匿名函數是一個閉包 return i endendc1 = newCounter() -- 得到一個匿名函數的變量(閉包)print(c1()) -- 調用匿名函數,打印出1print(c1()) -- 調用匿名函數,打印出2c2 = newCounter()print(c2()) --> 1print(c1()) --> 3print(c2()) --> 210. 五、控制語句
for int i = 0, 10, 2 do -- for循環,2表示步長,省略時為1 print("i = " .. i) -- .. 表示字符串連接符end -- 結束forif a > b then -- if條件判斷語句 print("a > b")else print("b > a")endwhile a > b do -- while循環 print("")endrepeat -- repeat-until循環 print("")until a > b11. 六、邏輯運算符 and、or、not
邏輯運算符認為false和nil是假(false),其他為真,0也是true.
a and b -- 如果a為false,則返回a,否則返回ba or b -- 如果a為true,則返回a,否則返回bx = x or v -- 如果x為false或者nil時則給x賦初始值v-- 等價于if not x then x = vend-- 三元運算符a ? b : c => a and b or c -- and 的優先級別比 or 高not -- not 的結果只返回false或true,作用類似于"非" "!"取反的意思print(not nil) -- trueprint(not false) -- trueprint(not 0) -- false12. 七、協同程序 coroutine
7.1 創建協同
co = coroutine.create(function () -- 創建一個協同函數,接收一個匿名函數,返回thread類型 print("hi")end)print(co) -- thread: 0x7fe1834127d07.2 協同的三個狀態:掛起態(suspended)、運行態(running)、停止態(dead)。
print(coroutine.status(co)) -- 查看協同的狀態,默認狀態是掛起態 suspendedcoroutine.resume(co) -- 改變協同的狀態為運行太 hiprint(coroutine.status(co)) -- 協同運行完以后將變量停止態 dead7.3 如此掛起正在運行的協同
co = coroutine.create(function () print("hi") coroutine.yield() -- 協同運行到此狀態將變成掛起 print("你好")end)coroutine.resume(co) -- hicoroutine.resume(co) -- 你好coroutine.resume(co) -- false,協同結束后將不能再使用7.4 協同數據交換
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)13. 八、數據結構 table
8.1 表的創建
arrays = {} -- 創建一個空表arrays[1] = "abc" -- 第一個索引值為1arrays[2] = 123arrays["key"] = "value" -- mapfor key, value in pairs(arrays) do -- 迭代table print(key .. " = " .. value)end8.2 表的增刪改查
list = {123} -- 初始化表list[2] = "abc" -- 增list.x = 123list.y = 987list[1] = nil -- 刪list.y = nillist[2] = 456 -- 改list.x = 987print(list[2]) -- 查print(list.x)print(list['x'])8.3 數組
list = {} -- 初始空化數組,數組的下標是整數,遵循Lua的標準,下標從1開始list[1] = "abc"list[2] = "edg"list[3] = "hij"8.4 矩陣(二維數組)
mt = {} -- 創建矩陣matrixfor i = 1, N do -- 創建N行 mt[i] = {} -- 每行都是一個數組(table元素) for j = 1, M do -- 創建M列 mt[i][j] = "a" -- 第N行第M行的值 endend8.5 鏈表
Singly-linked-list.svglist = nillist = {next = list, value = "hello3"}list = {next = list, value = "hello2"}list = {next = list, value = "hello1"}-- 遍歷local l = listwhile l do print(l.value) l = l.nextend14. 九、metatable 元表
9.1 元表與元方法
元表也是普通表
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 -- 更新表,如果增加一個不存在的元素,會去查詢,有直接用,否則增加9.2 表的代理
記錄下表的增查記錄
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 -- 返回代理表,即所有操作都是直接操作代理表endp = setProxy({})p[2] = 'abcdefg' -- 更新了 2 元素的值為 abcdefgprint(p[2]) -- 訪問了2元素15. 十、環境
10.1 全局變量 _G
> _G["ewgegw"] = "ddddddgege"> table.foreach(_G, print)string table: 0x7ffce3407a60xpcall function: 0x7ffce3404780package table: 0x7ffce3405780tostring function: 0x7ffce3405020print function: 0x7ffce3405160os table: 0x7ffce34073e0unpack function: 0x7ffce34050d0ewgegw ddddddgege -- 上面添加的全局變量require function: 0x7ffce3405e70getfenv function: 0x7ffce3404db0setmetatable function: 0x7ffce3404f60next function: 0x7ffce3404d20assert function: 0x7ffce3404a80tonumber function: 0x7ffce3404fc0io table: 0x7ffce3406bd0rawequal function: 0x7ffce34051b0collectgarbage function: 0x7ffce3404ad0getmetatable function: 0x7ffce3404e00module function: 0x7ffce3405e20rawset function: 0x7ffce3405260math table: 0x7ffce3408290debug table: 0x7ffce3408c50pcall function: 0x7ffce3404d70table table: 0x7ffce3405f10newproxy function: 0x7ffce34052e0type function: 0x7ffce3405080coroutine table: 0x7ffce3405380 -- 對應的是協同的表_G table: 0x7ffce3404110select function: 0x7ffce3404ec0gcinfo function: 0x7ffce3404150pairs function: 0x7ffce34048c0rawget function: 0x7ffce3405210loadstring function: 0x7ffce3404cc0ipairs function: 0x7ffce3404830_VERSION Lua 5.1dofile function: 0x7ffce3404bd0setfenv function: 0x7ffce3404f10load function: 0x7ffce3404c70error function: 0x7ffce3404c20loadfile function: 0x7ffce3404e60> table.foreach(_G.os, print)10.2 非全局變量 setfenv
--pack.lua---------------------------------------------------------------------local P = {}-- 改變P表的__index,這里的_G代表全局環境setmetatable(P, {__index = _G})-- 改變當前的環境為P,setfenv前的所有定義都是在全局環境中進行的,后面的則都是在新環境中進行的,互不影響setfenv(1, P)-- 聲明的add函數在環境P中,如果要在外部訪問必須P.addfunction add(x, y) print(x .. ' + ' .. y .. ' = ' .. (x + y)) -- 由于當前新的環境中沒有print函數,但是__index指向的是全局環境,所以print是全局的函數endreturn P--pack1.lua--------------------------------------------------------------------local P = {}-- 如果需要改變環境后使用全局環境的方法需要記住,這種方法比上面的要快local print = print-- 改變當前的環境為Psetfenv(1, P)-- 聲明的add函數在環境P中,如果要在外部訪問必須P.addfunction add(x, y) print(x .. ' + ' .. y .. ' = ' .. (x + y))end-- 私有方法local function div(x, y)endreturn P--main.lua---------------------------------------------------------------------local p = require 'pack'p.add(12, 34)local p1 = require 'pack1'p1.add(43, 19)16. 十一、包 package
11.1 包的定義
-- student.luastudent = {}function student.sayHi() print('Hello')endreturn student-- 使用student = require("student")student.sayHi() -- Hello11.2 私有函數local function _add(x, y) -- 私有局部函數 return x + yendutils = { -- utils包 add = _add -- 對外公開的函數}return utils17. 十二、面向對象
12.1 類與繼承
--Person.lualocal Person = {name = ''}function Person:getName() return self.nameendfunction Person:setName(name) self.name = nameendfunction Person:new(object) object = object or {} setmetatable(object, {__index = self}) -- 元表 類似繼承的意思 return objectendreturn Person--main.lua-- 類local Person = require 'Person'-- 對象local student = Person:new({age = 23})student:setName('Tom')print('name: ' .. student:getName() .. ' age: ' .. student.age)12.2 多重繼承
實際就是記住所有父類,然后訪問不存在的元素的時候去查詢哪個父類中有,有就執行
local function search (k, plist) for i=1, table.getn(plist) do local v = plist[i][k] -- 去所有父類中獲取 if v then return v end endendfunction 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 oend12.3 私有性
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 publicendlocal account = createAccount('Tom')print(account.name) -- 無法訪問,因為沒有公開18. 十三、weak table
t = {name = 'table'} -- 創建一個普通表setmatetable(t, {__made = 'k'}) -- k表示t表中的keys是weak的,v表示t表中的values是weak的k = {} -- 創建一個空表,此時{}被k引用,引用值為1t[k] = 1 -- 把空表作為key,由于t表的key是weak的,所以k值的引用如果為0則會被gc回收,如k = {} -- 把k指向另一個新的{},則舊的{}引用值減1變成0了,目前t[k] = 1還有效t[k] = 2 -- 把新的{}作為key,值是2collectgarbage() -- 調用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] = v1a[2] = v2v1 = v2collectgarbage(); -- 調用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] = vv = {} -- value重新引用新值,舊值被gc,如果舊值在table則對應的記錄被清空a[2] = va[k] = 1k = {} -- key重新引用新值,舊值被gc,如果舊值在table則對應的記錄被清空a[k] = 2collectgarbage(); -- 調用GC,清掉weak表中沒有引用的內存for k, v in pairs(a) do print(v)end19. 十四、標準庫
19.1. 14.1 數學庫 Mathematical Functions
函數 說明math.abs (x) 求絕對值math.acos (x) 求反余弦math.asin (x)math.atan (x)math.atan2 (y, x)math.ceil (x)math.cos (x)math.cosh (x)math.deg (x)math.exp (x)math.floor (x)20. 14.2 table庫
函數 說明table.concat (table [, sep [, i [, j]]]) 拼接成字符串,sep代表連接符,i開始位置,j結束位置table.insert (table, [pos,] value) 插入一個元素,默認是最后一個,pos指定位置table.maxn (table) 獲取最大長度table.remove (table [, pos]) 刪除一個元素,默認刪除最后一個,pos指定位置table.sort (table [, comp]) 排序tables = {1, 2, 3, 4, 5, 6, 7}print(#tables) -- 5.1開始使用#獲取長度 -- 7table.insert(tables, 8)print(table.concat(tables)) -- 12345678table.insert(tables, 1, 0)print(table.concat(tables)) -- 012345678print(table.maxn(tables)) -- 9table.remove(tables)print(table.concat(tables)) -- 01234567table.remove(tables, 5)print(table.concat(tables)) -- 0123567print(table.concat(tables, ',')) -- 0,1,2,3,5,6,7print(table.concat(tables, '-', 2)) -- 1-2-3-5-6-7print(table.concat(tables, '=', 1, 4)) -- 0=1=2=3table.sort(tables)print(table.concat(tables)) -- 0123567table.sort(tables, function(t1, t2) if t1 > t2 then return true else return false endend)print(table.concat(tables)) -- 765321021. 14.3 string庫
函數 說明string.byte (s [, i [, j]]) 把字符轉換成ASCII碼string.char (…) 把ASCII碼轉換成字符string.dump (function)string.find (s, pattern [, init [, plain]]) 查找,pattern查找的字符串,init從那里開始默認為1,plainstring.format (formatstring, …) 格式化字符串22. 14.4 io庫
函數 說明io.close ([file]) 等效file:close(),如果沒有file則關閉默認輸出io.flush () 等效file:flush()io.input ([file])io.lines ([filename]) 等效io.input():lines()io.open (filename [, mode]) 打開一個文件,模式:r,w,a,r+,w+,a+io.output ([file])io.popen (prog [, mode]) 依賴系統的,不是所有平臺都能用io.read (…) 等效io.input():readio.tmpfile () 創建一個臨時文件,當程序退出時自動刪除io.type (obj) 判斷obj的類型,如果返回file是一個打開的文件句柄,返回close file是一個關閉的文件句柄,nil不是文件io.write (…) 等效io.output():writefile:close () 關閉文件,會自動gc掉,但時間不確定file:flush () 保存任何數據到文件中file:lines () 迭代文件的每一行file:read (…) 讀取文件,*n,*a,*l,numberfile:seek ([whence] [, offset]) 指定位置,默認是cur,1,set,endfile:setvbuf (mode [, size]) 設置buff緩存,no,full,linefile:write (…) 寫文件,參數必須是string或者numberlocal 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)endfor line in io.lines('tabletest.lua') do --print(line)end23. 14.5 os庫
函數 說明os.clock () 返回程序所使用的cpu時間os.date ([format [, time]]) 當前系統日期,或格式化某個日期os.difftime (t2, t1) 時間差os.execute ([command]) 執行shell命令os.exit ([code]) 調用C的exit函數os.getenv (varname) 獲取系統環境變量,變量名,不包含$os.remove (filename) 刪除文件,文件名os.rename (oldname, newname) 修改文件名os.setlocale (locale [, category]) 設置地區,"all", “collate”, “ctype”, “monetary”, “numeric”, or “time”os.time ([table]) 返回當前時間或把時間保存在table中,os.tmpname () 臨時文件名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 ())14.6 debug庫
函數 說明
24. 十五、標準庫
15.1 堆棧,后進先出原則
25. 壓入
函數 說明(棧底最后一個元素的索引是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*, …) 壓入一個格式化的stringlua_pushvfstring(lua_State*, const char*, va_list) 同上,只是接收一個va_listlua_pushlstring(lua_State*, const char*, size_t); 壓入長字符串lua_pushliteral(lua_State*, const char*) 壓入文字lua_pushthread(lua_State*) 壓入一個線程?26. 判斷類型
函數 說明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) 是否是tablelua_isthread(lua_State*, int) 是否是線程lua_isuserdata(lua_State*, int) 是否是用戶類型,包括full和lightlua_type(lua_State*, int) 返回元素的類型,對應LUA_TNIL等枚舉lua_typename(lua_State*, int) 返回元素的類型名稱27. 獲取棧中的元素并轉換成C類型
函數 說明 返回值類型lua_toboolean(lua_State*, int) 把元素轉換成C的布爾類型的值 intlua_tocfunction(lua_State*, int) 把元素轉換成C的函數 lua_CFunctionlua_tointeger (lua_State*, int) lua_Integerlua_tolstring (lua_State*, int, size_t *len) const char*lua_tonumber (lua_State*, int) lua_Numberlua_topointer (lua_State*, int) const void*lua_tostring (lua_State*, int) const char*lua_tothread (lua_State*, int) lua_Statelua_touserdata (lua_State*, int) void*棧內元素的操作函數 說明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
原文地址:http://blog.linguofeng.com/pages/language/lua.html
總結
以上是生活随笔為你收集整理的Lua-简洁、轻量、可扩展的脚本语言的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。