使用者:Greykid/參考手冊/Lua 語言入門
《真·女神轉生》大係數據編纂和樣式設計統一模塊 「模塊:Psk」 的參考手冊。操作細則和貢獻方式,請進入《真·女神轉生》大系編輯者群(832689630)尋求進一步幫助。
本文概述使用 Lua 編程語言編寫 Scribunto MediaWiki 模塊化程序的基礎知識。
初學編程
本文默認讀者已經學會至少一種編程語言(C++、Python、Java 或 Visual Basic),有一定的編程經驗。如果沒有學過編程,請先行閱讀普通高中信息技術選修1《算法與程序設計》了解編程原理。
熟練使用 Lua 編寫模塊,還需要一定的前端基礎(HTML/CSS/Javascript)。
Lua 語言概述
基礎
Lua 對大小寫敏感。
Lua 是動態類型語言,變量不需要類型定義,只需要為變量賦值。值可以存儲在變量中,作為參數傳遞或結果返回。
Lua 中的基本數據類型:nil(無效值)、boolean、number(雙精度浮點數)、string、function、table(列表)。
Lua 提供運行時字符串與數字之間的自動轉換。
Lua 中的變量全是全局變量,那怕是語句塊或是函數裡,除非用 local 顯式聲明為局部變量。局部變量的作用域為從聲明位置開始到所在語句塊結束。
變量的默認值均為 nil。
Lua 的字符串可以用單引號,也可以用雙引號包括。
布爾類型只有 nil 和 false 是 false。數字 0、''
、'\0'
都是 true。
Lua 語言編寫注釋,在行注釋前添加兩個減號:-- 此为注释
運算符
Lua 的取餘數運算符為 %
,冪運算為 ^
。
「不等於」運算符為 ~=
。邏輯運算符為 and
、or
、not
。
Lua 中 and 和 or 都是短路求值(short-cur evaluation),也就是說,它們只會在需要時才去評估第二個操作數。
使用 ..
連接兩個字符串,使用一元運算符 #
返回字符串或 table 的長度。
運算符優先級:
^ not - (unary) * / % + - .. < > <= >= ~= == and or
條件和循環語句
if 條件語句:
if (condition1) then ... elseif (condition2) then ... elseif (condition3) then ... else ... end
while 循環語句:
while (condition) do ... end
break 跳出最內層的循環。
for 循環語句:
for var = exp1, exp2, exp3, ... do ... end for i, v in pairs(list) do ... end for i, v in ipairs(list) do ... end
注意:ipairs 這個迭代器只能遍歷所有數組下標的值,這是前提,也是和 pairs 的最根本區別,也就是說如果 ipairs 在迭代過程中是會直接跳過所有手動設定 key 值的變量。
特別注意一點,和其他多數語言不同的地方是,Lua 的下標是從 1 開始的。
table
Lua 的 table 其實就是一個字典(Key-Value)數據結構。
JackFrost = { age = 101, namezh = '傑克霜精', [3.14] = 'Pi', ['Black Frost'] = { namezh = '邪惡霜精', namejp = 'ジャアクフロスト', isGay = false } }
Lua 語言本身採用一種語法糖,支持以 a.name
的形式表示 a['name']
。
函數
Lua 的函數和 Javascript 的很像。
function fib(n) if n < 2 then return 1 end return fib(n - 2) + fib(n - 1) end
Lua 中可以將函數作為參數傳遞給函數。
function newCounter() local i = 0 return function() -- 匿名函数 i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 function myPower(x) return function(y) return y^x end end power2 = myPower(2) power3 = myPower(3) print(power2(4)) -- 4的2次方 print(power3(5)) -- 5的3次方
與 Python 語言類似,可以在一條語句上賦多個值。下面的代碼中,因為只有 3 個變量,所以第四個值被丟棄。函數也可以返回多個值。
name, age, isGay = "Jack Frost", 100, false, "Hee-Ho~" function getUserInfo() return "Jack Frost", 100, false, "Hee-Ho~" end name, age, isGay = getUserInfo()
在 Lua 中沒有函數「重載」的語法。但是,調用函數時參數可以少填或不填,此時未賦值的參數為 nil。
函數前面加上 local 就是局部函數。
多模塊
可以直接使用 require('model_name')
來載入另一個 lua 模塊。相當於將 require 語句處替換為另一個模塊的全部代碼。
local getGames = require('Module:Psk/Gamedata') -- 以下为 Module:Psk/Gamedata 中的内容: local games = { ... } return { games = games }
接入 MediaWiki
Scribunto MediaWiki 使用 {{ #invoke: 模块名 | 主函数名 }}
調用模塊。
模塊編寫範例:
local p = {} -- p 是 package 的意思 function p.hello(frame) return 'Hello, world!' end return p
模塊的命名空間一定要是「Module」或「模塊」。
Lua 語言本身為腳本語言。實現以類似模板的形式({{ #invoke: 模块名 | 主函数名 | 管道传参 }}
)調用模塊,需要藉助 模塊:Arguments。
local getArgs = require('Module:Arguments').getArgs local p = {} local function makeInvokeFunction(funcName) return function (frame) local args = getArgs(frame, {parentOnly = true}) return p[funcName](args) end end p.foo = makeInvokeFunction('_foo') function p._foo(args) ... end return p
更多
想了解更多 Lua 語言的複雜語法,參見 Lua 5.1 參考手冊。
Scribunto MediaWiki 提供的官方 Lua 編程文檔:Lua reference manual。