2020-09-21 學(xué)習(xí)筆記3

所有內(nèi)容來自菜鳥教程关翎,這里記錄是為了幫助自己整理和記憶。

迭代器

利用for循環(huán)迭代數(shù)組

array = {"1","2","3",a=1,b=2,c=3}

for k,v in ipairs(array) do
    print(k,v)
end

按順序輸出非鍵值對(duì)的函數(shù)

array = {a=1,"1","2","3",b=2,c=3}

for k,v in pairs(array) do
    print(k,v)
end

輸出所有元素饥侵,其中非鍵值對(duì)的元素先按照順序輸出痊银,鍵值對(duì)的元素后輸出且順序隨機(jī)。

無狀態(tài)的迭代器

一個(gè)簡單的函數(shù)來實(shí)現(xiàn)迭代器類似ipairs航邢,實(shí)現(xiàn) 數(shù)字 n 的平方:

實(shí)例

function square(iteratorMaxCount,currentNumber)
  if currentNumber<iteratorMaxCount
  then
   currentNumber = currentNumber+1
  return currentNumber, currentNumber*currentNumber
  end
end

for i,n in square,3,0
do
  print(i,n)
end

以上實(shí)例輸出結(jié)果為:

1    1
2    4
3    9

迭代的狀態(tài)包括被遍歷的表(循環(huán)過程中不會(huì)改變的狀態(tài)常量)和當(dāng)前的索引下標(biāo)(控制變量)

ipairs 和迭代函數(shù)都很簡單耕赘,我們?cè)?Lua 中可以這樣實(shí)現(xiàn):

實(shí)例

function iter (a, i)
  i = i + 1
  local v = a[i]
  if v then
    return i, v
  end
end

function ipairs (a)
  return iter, a, 0
end

當(dāng) Lua 調(diào)用 ipairs(a) 開始循環(huán)時(shí),他獲取三個(gè)值:迭代函數(shù) iter膳殷、狀態(tài)常量 a鞠苟、控制變量初始值 0;然后 Lua 調(diào)用 iter(a,0) 返回 1, a[1](除非 a[1]=nil)秽之;第二次迭代調(diào)用 iter(a,1) 返回 2, a[2]……直到第一個(gè) nil 元素当娱。

多狀態(tài)的迭代器

很多情況下,迭代器需要保存多個(gè)狀態(tài)信息而不是簡單的狀態(tài)常量和控制變量考榨,最簡單的方法是使用閉包跨细,還有一種方法就是將所有的狀態(tài)信息封裝到 table 內(nèi),將 table 作為迭代器的狀態(tài)常量河质,因?yàn)檫@種情況下可以將所有的信息存放在 table 內(nèi)冀惭,所以迭代函數(shù)通常不需要第二個(gè)參數(shù)。

以下實(shí)例我們創(chuàng)建了自己的迭代器:

array = {"Google", "Runoob"}

function elementIterator (collection)
   local index = 0
   local count = #collection
   -- 閉包函數(shù)
   return function ()
      index = index + 1
      if index <= count
      then
         --  返回迭代器的當(dāng)前元素
         return collection[index]
      end
   end
end

for element in elementIterator(array)
do
   print(element)
end

以上實(shí)例中我們可以看到掀鹅,elementIterator 內(nèi)使用了閉包函數(shù)散休,實(shí)現(xiàn)計(jì)算集合大小并輸出各個(gè)元素。

事實(shí)上這部分沒看太懂乐尊,需要后面用到再仔細(xì)研究研究一下戚丸。

Table 操作

以下列出了 Table 操作常用的方法:

序號(hào) 方法 & 用途
1 table.concat (table [, sep [, start [, end]]]):concat是concatenate(連鎖, 連接)的縮寫. table.concat()函數(shù)列出參數(shù)中指定table的數(shù)組部分從start位置到end位置的所有元素, 元素間以指定的分隔符(sep)隔開鼓鲁。
2 table.insert (table, [pos,] value):在table的數(shù)組部分指定位置(pos)插入值為value的一個(gè)元素. pos參數(shù)可選, 默認(rèn)為數(shù)組部分末尾.
3 table.maxn (table)指定table中所有正數(shù)key值中最大的key值. 如果不存在key值為正數(shù)的元素, 則返回0目锭。(Lua5.2之后該方法已經(jīng)不存在了,本文使用了自定義函數(shù)實(shí)現(xiàn))
4 table.remove (table [, pos])返回table數(shù)組部分位于pos位置的元素. 其后的元素會(huì)被前移. pos參數(shù)可選, 默認(rèn)為table長度, 即從最后一個(gè)元素刪起冕香。
5 table.sort (table [, comp])對(duì)給定的table進(jìn)行升序排序供汛。

接下來我們來看下這幾個(gè)方法的實(shí)例。

t = {1, 5, 9, "zzz", "zzd", name = "zun"}
print(table.concat(t, ';'))
--輸出:1;5;9;zzz;zzd胁勺,鍵值對(duì)并沒有計(jì)入

注意:

當(dāng)我們獲取 table 的長度的時(shí)候無論是使用 # 還是 table.getn 其都會(huì)在索引中斷的地方停止計(jì)數(shù)世澜,而導(dǎo)致無法正確取得 table 的長度。

可以使用以下方法來代替:

function table_leng(t)
  local leng=0
  for k, v in pairs(t) do
    leng=leng+1
  end
  return leng;
end

Lua 模塊與包

模塊類似于一個(gè)封裝庫署穗,從 Lua 5.1 開始寥裂,Lua 加入了標(biāo)準(zhǔn)的模塊管理機(jī)制,可以把一些公用的代碼放在一個(gè)文件里案疲,以 API 接口的形式在其他地方調(diào)用封恰,有利于代碼的重用和降低代碼耦合度。

Lua 的模塊是由變量络拌、函數(shù)等已知元素組成的 table俭驮,因此創(chuàng)建一個(gè)模塊很簡單,就是創(chuàng)建一個(gè) table春贸,然后把需要導(dǎo)出的常量混萝、函數(shù)放入其中,最后返回這個(gè) table 就行萍恕。以下為創(chuàng)建自定義模塊 module.lua逸嘀,文件代碼格式如下:

-- 文件名為 module.lua
-- 定義一個(gè)名為 module 的模塊
module = {}
 
-- 定義一個(gè)常量
module.constant = "這是一個(gè)常量"
 
-- 定義一個(gè)函數(shù)
function module.func1()
    io.write("這是一個(gè)公有函數(shù)!\n")
end
 
local function func2()
    print("這是一個(gè)私有函數(shù)允粤!")
end
 
function module.func3()
    func2()
end
 
return module

由上可知崭倘,模塊的結(jié)構(gòu)就是一個(gè) table 的結(jié)構(gòu),因此可以像操作調(diào)用 table 里的元素那樣來操作調(diào)用模塊里的常量或函數(shù)类垫。

上面的 func2 聲明為程序塊的局部變量司光,即表示一個(gè)私有函數(shù),因此是不能從外部訪問模塊里的這個(gè)私有函數(shù)悉患,必須通過模塊里的公有函數(shù)來調(diào)用.


require 函數(shù)

Lua提供了一個(gè)名為require的函數(shù)用來加載模塊残家。要加載一個(gè)模塊,只需要簡單地調(diào)用就可以了售躁。例如:

require("<模塊名>")

或者

require "<模塊名>"

執(zhí)行 require 后會(huì)返回一個(gè)由模塊常量或函數(shù)組成的 table坞淮,并且還會(huì)定義一個(gè)包含該 table 的全局變量。

-- test_module.lua 文件
-- module 模塊為上文提到到 module.lua
require("module")
 
print(module.constant)
 
module.func3()

或者給加載的模塊定義一個(gè)別名變量陪捷,方便調(diào)用:

-- test_module2.lua 文件
-- module 模塊為上文提到到 module.lua
-- 別名變量 m
local m = require("module")
 
print(m.constant)
 
m.func3()

加載機(jī)制

對(duì)于自定義的模塊回窘,模塊文件不是放在哪個(gè)文件目錄都行,函數(shù) require 有它自己的文件路徑加載策略市袖,它會(huì)嘗試從 Lua 文件或 C 程序庫中加載模塊啡直。

require 用于搜索 Lua 文件的路徑是存放在全局變量 package.path 中,當(dāng) Lua 啟動(dòng)后,會(huì)以環(huán)境變量 LUA_PATH 的值來初始這個(gè)環(huán)境變量付枫。如果沒有找到該環(huán)境變量烹玉,則使用一個(gè)編譯時(shí)定義的默認(rèn)路徑來初始化驰怎。

當(dāng)然阐滩,如果沒有 LUA_PATH 這個(gè)環(huán)境變量,也可以自定義設(shè)置县忌,在當(dāng)前用戶根目錄下打開 .profile 文件(沒有則創(chuàng)建掂榔,打開 .bashrc 文件也可以),例如把 "~/lua/" 路徑加入 LUA_PATH 環(huán)境變量里:

#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"

文件路徑以 ";" 號(hào)分隔症杏,最后的 2 個(gè) ";;" 表示新加的路徑后面加上原來的默認(rèn)路徑装获。

接著,更新環(huán)境變量參數(shù)厉颤,使之立即生效穴豫。

source ~/.profile

這時(shí)假設(shè) package.path 的值是:

/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua

那么調(diào)用 require("module") 時(shí)就會(huì)嘗試打開以下文件目錄去搜索目標(biāo)。

/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua

如果找過目標(biāo)文件逼友,則會(huì)調(diào)用 package.loadfile 來加載模塊精肃。否則,就會(huì)去找 C 程序庫帜乞。

搜索的文件路徑是從全局變量 package.cpath 獲取司抱,而這個(gè)變量則是通過環(huán)境變量 LUA_CPATH 來初始。

搜索的策略跟上面的一樣黎烈,只不過現(xiàn)在換成搜索的是 so 或 dll 類型的文件习柠。如果找得到,那么 require 就會(huì)通過 package.loadlib 來加載它照棋。

C 包

Lua和C是很容易結(jié)合的资溃,使用 C 為 Lua 寫包。

與Lua中寫包不同烈炭,C包在使用以前必須首先加載并連接溶锭,在大多數(shù)系統(tǒng)中最容易的實(shí)現(xiàn)方式是通過動(dòng)態(tài)連接庫機(jī)制。

Lua在一個(gè)叫l(wèi)oadlib的函數(shù)內(nèi)提供了所有的動(dòng)態(tài)連接的功能梳庆。這個(gè)函數(shù)有兩個(gè)參數(shù):庫的絕對(duì)路徑和初始化函數(shù)暖途。所以典型的調(diào)用的例子如下:

local path = "/usr/local/lua/lib/libluasocket.so"
local f = loadlib(path, "luaopen_socket")

loadlib 函數(shù)加載指定的庫并且連接到 Lua,然而它并不打開庫(也就是說沒有調(diào)用初始化函數(shù))膏执,反之他返回初始化函數(shù)作為 Lua 的一個(gè)函數(shù)驻售,這樣我們就可以直接在Lua中調(diào)用他。

如果加載動(dòng)態(tài)庫或者查找初始化函數(shù)時(shí)出錯(cuò)更米,loadlib 將返回 nil 和錯(cuò)誤信息欺栗。我們可以修改前面一段代碼,使其檢測錯(cuò)誤然后調(diào)用初始化函數(shù):

local path = "/usr/local/lua/lib/libluasocket.so"
-- 或者 path = "C:\\windows\\luasocket.dll",這是 Window 平臺(tái)下
local f = assert(loadlib(path, "luaopen_socket"))
f()  -- 真正打開庫

一般情況下我們期望二進(jìn)制的發(fā)布庫包含一個(gè)與前面代碼段相似的 stub 文件迟几,安裝二進(jìn)制庫的時(shí)候可以隨便放在某個(gè)目錄消请,只需要修改 stub 文件對(duì)應(yīng)二進(jìn)制庫的實(shí)際路徑即可。

將 stub 文件所在的目錄加入到 LUA_PATH类腮,這樣設(shè)定后就可以使用 require 函數(shù)加載 C 庫了臊泰。

說實(shí)話關(guān)于這部分也沒怎么看懂,以后用到再回來仔細(xì)研究吧蚜枢。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缸逃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厂抽,更是在濱河造成了極大的恐慌需频,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筷凤,死亡現(xiàn)場離奇詭異昭殉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)藐守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門挪丢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吗伤,你說我怎么就攤上這事吃靠。” “怎么了足淆?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵巢块,是天一觀的道長。 經(jīng)常有香客問我巧号,道長族奢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮廊敌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘囤锉。我一直安慰自己,他們只是感情好驱入,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布可霎。 她就那樣靜靜地躺著拾因,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上签孔,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天罐盔,我揣著相機(jī)與錄音捏顺,去河邊找鬼。 笑死昌执,一個(gè)胖子當(dāng)著我的面吹牛煤禽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼恳啥,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了丹诀?” 一聲冷哼從身側(cè)響起钝的,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铆遭,沒想到半個(gè)月后硝桩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枚荣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年碗脊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橄妆。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡衙伶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呼畸,到底是詐尸還是另有隱情痕支,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布蛮原,位于F島的核電站卧须,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏儒陨。R本人自食惡果不足惜花嘶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹦漠。 院中可真熱鬧椭员,春花似錦、人聲如沸笛园。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至埋同,卻和暖如春州叠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凶赁。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工咧栗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人虱肄。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓致板,卻偏偏與公主長得像,于是被迫代替她去往敵國和親咏窿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子斟或,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355