註解與文件字串 |
|
有時我們會想將一些元資料與物件關聯起來,例如物件的文件或類型資訊。我們可以將這些資料儲存在物件中的欄位內,藉此修改物件的實作,但這有可能會導致一些問題,特別是在這個物件屬於別人的時候(資訊隱藏)。實際上,如果是函式或唯讀表格,我們可能無法修改物件。
一種解決方法基本上是建立一個將物件(作為鍵)對映到它們的標註(作為值)的全球表格。根據定義,物件擁有獨特的識別碼,因此可以在表格中作為唯一的鍵。以這種方式,物件本體並不會被修改。由於全球表格包含物件的參考,此舉會對垃圾收集造成些許干擾,但我們可以使用 Lua 中的「弱表格」來達成此目的(請參閱《Lua 程式設計》一書中的 LuaBooks)。
以下是將文件字串 [1] 套用到 Lua 物件的方法。
local docstrings = setmetatable({}, {__mode = "kv"}) function document(str) return function(obj) docstrings[obj] = str; return obj end end function help(obj) print(docstrings[obj]) end document[[Print the documentation for a given object]](help) document[[Add a string as documentation for an object]](document) f = document[[Print a hello message]]( function() print("hello") end ) f() help(f)
請注意:如果標註是指回標註物件的物件,垃圾收集可能會失敗(請參閱 GarbageCollectingWeakTables)。
Perl 中的「反向物件」使用了有點類似的模式。
可以在其他情況套用此模式,例如在不對物件進行任何變更的情況下將元資料套用到物件。這些情況包括在 Python 中使用的函式註解 [2] [3]。
以下替換語法可以用來套用函式註解到函式,會比較好
random = docstring[[Compute random number.]] .. typecheck("number", '->', "number") .. function(n) return math.random(n) end
函式註解可以基本上以這種方式實作
mt = {__concat = function(a,f) return function(...) print("decorator", table.concat(a, ","), ...) return f(...) end end } function typecheck(...) return setmetatable({...}, mt) end function docstring(...) return setmetatable({...}, mt) end
在這裡,在函式註解和函式之間使用運算子(..
)可以避免函式周圍出現括號,並讓註解鏈串在一起更好看。我們要這個運算子具有右結合性,因此這個運算子唯一可選擇的選項為 ..
和 ^
。
另請參閱 LuaTypeChecking,了解用於表達函式參數和回傳類型的註解具體用法。
--DavidManura,2007-02