lua進階教程

_G.print("hello lua, version is", _VERSION)

lua官網(wǎng)
在線運行代碼

table面向?qū)ο笳Z法糖

lua對table中的函數(shù)調(diào)用做了優(yōu)化押蚤,使用起來像類方法机打,增加了個特殊變量self褥紫。

local t = {x=1,}
t.Add = function(self)
    self.x = self.x + 1
end
t.Add(t)

print(t.x) -- 2
local t = {x=1,}
function t:Add()
    self.x = self.x + 1
end
t:Add()
print(t.x) -- 2

兩個例子效果一樣寸潦。第二個算是語法糖,隱含定義了第一個參數(shù)變量self答憔,方便使用价涝。

閉包 closure

lua里的閉包就是函數(shù)炮赦。特殊之處,在于閉包綁定了一些局部變量向叉,lua實現(xiàn)里稱為upvalue锥腻。

function get_closure()
 -- 這個局部變量被下面的函數(shù)保存了
 local x = 1
 local add = function() x = x + 1 end
 local get = function() return x end
 -- add和get使用的是同一個x
 return get,add
end
local get,add = get_closure()
print(get()) -- 1
add()
print(get()) -- 2

閉包綁定局部變量時是引用綁定,多個閉包可以共享同一個局部變量母谎。

元表 metatable

lua提供了元表機制瘦黑,可用于擴展lua的功能,如:模擬類奇唤,模擬原型幸斥。
理解上就是用一個table描述另一個table的一些特定情況如何處理。

t = {}
print(t.x) -- nil
mt = {
    -- 當(dāng)table不存在某個key值時咬扇,調(diào)用這個函數(shù)
    __index = function(_,key)
        return key .. " not find"
    end,
}
setmetatable(t,mt)
print(t.x) -- x not find

setmetatable(t,{
    -- 當(dāng)t中不存在某個key值甲葬,嘗試從這個表中獲取
    __index = {x = "x save in metatable"}
})
print(t.x) -- x save in metatable

上面的例子演示了最常見的元表項__index,還有其他元表項懈贺。

元表key 描述
__index 讀取table[key]经窖,值為nil,會檢查這個元表項梭灿。
是function画侣,就獲取函數(shù)返回值。不是堡妒,就遞歸讀取配乱。
__newindex 寫入table[key] = value,原值為nil涕蚤,檢查這個元表項宪卿。
是function,調(diào)用之万栅。不是佑钾,遞歸寫入。
__gc 垃圾回收時調(diào)用烦粒,常用于userdata類型休溶,相當(dāng)于析構(gòu)函數(shù)
__call 使用obj()時調(diào)用代赁,如果obj不是函數(shù)的話
__mode 值是個字符串。用于定義弱引用兽掰,弱引用不能阻止垃圾回收芭碍。
里面有k俊戳,則key是弱引用姐浮;里面有v,則value是弱引用
__concat 自定義..運算符
__eq 自定義==運算符
__add 自定義+運算符
__len 自定義#運算符
__lt 自定義<運算符
... 還有些其他的操作

注意:

  • 在lua里setmetatable只能修改table類型的元表垫言,可以在c里修改其他類型數(shù)據(jù)的元表
  • 在lua中存在元表保護模式杉女,如果原來的元表有__metatable字段瞻讽,那該元表不能被替換。

協(xié)程 coroutine

lua實現(xiàn)了協(xié)程熏挎。
協(xié)程有些像線程速勇,函數(shù)調(diào)用可以被中斷,然后再從中斷的地方繼續(xù)執(zhí)行坎拐。
協(xié)程與線程不同的地方在于烦磁,同一時刻只有一個協(xié)程處于運行狀態(tài),沒有互斥鎖的使用哼勇。
經(jīng)典的生產(chǎn)者消費者的例子:

producer = coroutine.create(function()
    for x = 1,2 do
        print("生產(chǎn) --> 第" .. x .. "個產(chǎn)品")
        coroutine.yield(x)
    end
    print("生產(chǎn)者結(jié)束生產(chǎn)")
end)

function consumer()
    while true do
        local _,x = coroutine.resume(producer)
        if x then
            print("消費 <-- 第" .. x .. "個產(chǎn)品")
        else
            print("消費者離場")
            break
        end
    end
end

consumer()

輸出的結(jié)果:

生產(chǎn) --> 第1個產(chǎn)品
消費 <-- 第1個產(chǎn)品
生產(chǎn) --> 第2個產(chǎn)品
消費 <-- 第2個產(chǎn)品
生產(chǎn)者結(jié)束生產(chǎn)
消費者離場

模擬類·綜合應(yīng)用

使用table和閉包模擬類封裝都伪。

function New(name)
    local obj = {}
    local _name = name or "default name"

    obj.PrintName = function ()
        print(_name)
    end
    obj.SetName = function (name)
        _name = name
    end
    return obj
end
 
local obj = New()
obj.PrintName() -- default name
obj.SetName("new name")
obj.PrintName() -- new name

使用元表模擬類,可以實現(xiàn)繼承猴蹂。下面的例子實現(xiàn)的簡單的單繼承院溺。

-- 單繼承框架
function class(class_name,base_class)
    local cls = {__name = class_name}
    cls.__index = cls
    function cls:new(...)
        local obj = setmetatable({}, cls)
        cls.ctor(obj,...)
        return obj
    end
    if base_class then
        cls.super = base_class
        setmetatable(cls,{__index = base_class})
    end
    return cls
end
 
-- 使用
BaseClass = class("base")
function BaseClass:ctor()
end
function BaseClass:Say()
    print(self.__name .. " say")
end
 
DerivedClass = class("derived",BaseClass)
 
local base = BaseClass.new()
local derived = DerivedClass.new()
base:Say() -- base say
derived:Say() -- derived say

c擴展

lua和c交互時使用棧來傳遞參數(shù)。簡單例子演示

static int abs(lua_State *L)                    // [-0, +1, -]
{
    double n = luaL_checknumber(L, 1);
    n = (n > 0 ? n : -n);
    lua_pushinteger(L, n);
    return 1;// 返回值個數(shù):1個
}
 
static const luaL_Reg libs[] = {
    {"abs",abs},
    {NULL,NULL}
};
 
LUALIB_API int luaopen_test(lua_State *L) {
    luaL_register(L, "test", libs);// test 是模塊名
    return 1;
}

lua使用 print(test.abs(-1))磅轻,棧的變化


注釋[-0, +1, -]簡述了棧的變化珍逸,出棧0個,入棧1個聋溜。-表示不拋異常谆膳。

lua提供很多操作棧的API用于擴展,這兒講的簡單了撮躁,擴展閱讀漱病。

lua的C API
操作lua棧

其他

module模塊【5.1版本有用,之后就廢棄了】

lua提供了module來實現(xiàn)模塊管理把曼。

local print = print -- 注意這行
module("hello")

msg = "hello world"
function printHelloWorld()
    print(msg)
end

這兒的msg和printHelloWorld定義時沒有使用local杨帽,但是他們不是簡單的全局變量。
他們是模塊的全局變量嗤军,外部使用hello.printHelloWorld()注盈。

例子中第一行的local print=print,在這兒是一定要加的叙赚,不然module里不是使用print老客。
有個簡單的方法module("hello",package.seeall)僚饭,這樣module里可以訪問所有的全局變量。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末胧砰,一起剝皮案震驚了整個濱河市鳍鸵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌尉间,老刑警劉巖偿乖,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異乌妒,居然都是意外死亡汹想,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門撤蚊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人损话,你說我怎么就攤上這事侦啸。” “怎么了丧枪?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵光涂,是天一觀的道長。 經(jīng)常有香客問我拧烦,道長忘闻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任恋博,我火速辦了婚禮齐佳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘债沮。我一直安慰自己炼吴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布疫衩。 她就那樣靜靜地躺著硅蹦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闷煤。 梳的紋絲不亂的頭發(fā)上童芹,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音鲤拿,去河邊找鬼假褪。 笑死,一個胖子當(dāng)著我的面吹牛皆愉,可吹牛的內(nèi)容都是我干的嗜价。 我是一名探鬼主播艇抠,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼久锥!你這毒婦竟也來了家淤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤瑟由,失蹤者是張志新(化名)和其女友劉穎絮重,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歹苦,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡青伤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了殴瘦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狠角。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蚪腋,靈堂內(nèi)的尸體忽然破棺而出丰歌,到底是詐尸還是另有隱情,我是刑警寧澤屉凯,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布立帖,位于F島的核電站,受9級特大地震影響悠砚,放射性物質(zhì)發(fā)生泄漏晓勇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一灌旧、第九天 我趴在偏房一處隱蔽的房頂上張望绑咱。 院中可真熱鬧,春花似錦节榜、人聲如沸羡玛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽稼稿。三九已至,卻和暖如春讳窟,著一層夾襖步出監(jiān)牢的瞬間让歼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工丽啡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谋右,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓补箍,卻偏偏與公主長得像改执,于是被迫代替她去往敵國和親啸蜜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Nginx API for Lua Introduction ngx.arg ngx.var.VARIABLE C...
    吃瓜的東閱讀 5,717評論 0 5
  • 第一篇 語言 第0章 序言 Lua僅讓你用少量的代碼解決關(guān)鍵問題辈挂。 Lua所提供的機制是C不擅長的:高級語言衬横,動態(tài)...
    testfor閱讀 2,651評論 1 7
  • 自己所在的城市拇泣,有了冬天該有的模樣噪叙,室外刮風(fēng),室內(nèi)空氣有些許悶霉翔,主要是怕冷嘛睁蕾,關(guān)上門,開心呢迎接冬天給我們的養(yǎng)生節(jié)...
    換氧閱讀 191評論 0 0
  • 剛開始照這個貼子(http://blog.csdn.net/zou_pl/article/details/7262...
    素子姐閱讀 826評論 0 1
  • 以前用過一個本子早龟,很不經(jīng)心惫霸,那個本子也是很普通很普通,但是就是我忘不了葱弟,以至于我花了將近一年去找它,在淘寶猜丹,在商店...
    納殊閱讀 790評論 0 1