Lua元表有哪些讓人感覺到精彩的應用?
更新:
請仔細看題目, 題主問的是Lua的 元表(metatable) 的精彩應用,不是指通過Lua的其他特性實現的應用.所以回答里說的metalua moonscript,以及那個並不開源的迅雷Lua庫 jqbolt, 都不算對題.
fun.lua庫中雖然用到了幾處setmetatable, 但都算很常規的應用,算不上元表的精彩應用,不過那個庫倒是一個很好的Lua庫.-----------------此問題是用來拋磚引玉的.
除了最常見的用來實現object之外, 我還發現了用來做Python風格裝飾器的.裝飾器的鏈接: lua-users wiki: Decorators And Docstrings不知道各位還知道有什麼令人叫絕的應用, 歡迎回答!
Metalua, 各種lua黑科技, lua元編程, 我就問你怕不怕:
看幾個例子:
抽象語法樹:
local Q = require metalua.treequery
ast = +{ block:
local x=1
for y=1,10 do
print (x+i)
end
return math.cos(x) }
all_nodes = Q(ast)
The +{...} notation is a Metalua syntax which lets write an AST using regular syntax; its the equivalent to Lisps quasi-quoting forms (the anti-quote is written -{...}). Without the syntax sugar, ast would be written:
ast = {
`Local{ { `Id "x" }, { `Number 1 } },
`Fornum{ `Id "y", `Number 1, `Number 10, {
`Call{ `Id "print", `Op{ "add", `Id "x", `Id "i" } }
}
`Return{ `Call{ `Index{ `Id "math", `String "cos" }, `Id "x" } } }
自定義lua語法:
-{ extension trycatch }
print "1) no error"
try
print(" Hi")
end
print "2) caught error"
try
error "some_error"
catch x then
printf(" Successfully caught %q", x)
end
還有個玩意, MoonScript, a language that compiles to Lua,
我記得是基於lpeg搞的,
MoonScript is a dynamic scripting language that compiles into Lua. It gives you the power of one of the fastest scripting languages combined with a rich set of features.
See Luaclass Thing
name: "unknown"
class Person extends Thing
say_name: =&> print "Hello, I am #{@name}!"
with Person!
.name = "MoonScript"
say_name!
GM_RPC/gmrpc_lua at master · akirayu101/GM_RPC · GitHub
GM_RPC/rpc_base.lua at master · akirayu101/GM_RPC · GitHub
@於鑫
其實我見過一個很不錯的。rtsisyk/luafun · GitHub
來自orbit
function layout(web, args, inner_html)
return html{
head{
title(blog_title),
meta{ ["http-equiv"] = "Content-Type",
content = "text/html; charset=utf-8" },
link{ rel = stylesheet, type = text/css,
href = web:static_link(/style.css), media = screen }
},
body{
div{ id = "container",
div{ id = "header", title = "sitename" },
div{ id = "mainnav",
_menu(web, args)
},
div{ id = "menu",
_sidebar(web, args)
},
div{ id = "contents", inner_html },
div{ id = "footer", copyright_notice }
}
}
}
end
jqbolt算吧,lua里的jquery,https://github.com/zhenghecn/JQBolt
元表能玩的技術其實很多,不光是用來定義各種類型,也可以涵蓋代碼開發的糾錯等。一個簡單的例子:
setfenv(1, setmetatable({}, {
__index = function(self, key)
local val = _G[key] or error("The global " .. key .. " cant be found.", 2)
return val
end
}))
print(ture) -- Error: the global ture cant be found.
只要控制住定義環境,最常見的拼寫錯誤就很容易查出了,不然他們作為nil傳遞下去,程序隱患就很大了。當然,也有很多代碼檢查工具可用。
更進一步的是操作定義環境來模擬高級語言的定義模式,以下取自 kurapica/PLoop (算是自薦),和MoonScript不同,這是一個純lua的OOP庫,提供的功能和選擇也更多些:
import "System"
-- 定義Person類
class "Person" (function(_ENV)
-- 屬性定義
property "Name" { Type = String }
property "Age" { Type = Number }
-- 方法定義,因為控制了定義環境,也可以提供重載機能
-- __Arguments__是修飾類型,它實現了重載機能也提供參數驗證
-- 可以在開發時始用它來驗證調用,部署時去掉來提高速度
__Arguments__{ Person }
function Greet( self, another )
print( ("Hi %s, my names %s."):format(another.Name, self.Name) )
end
__Arguments__{ String }
function Greet( self, another )
print( ("Hi %s, my names %s."):format(another, self.Name) )
end
end)
-- 創建對象
ann = Person{ Name = "Ann" }
-- 重載方法用例
-- Hi King, my names Ann.
ann:Greet( "King" )
-- Hi King, my names Ann.
ann:Greet( Person{ Name = "King"} )
結合類和環境控制也能實現特殊的一些功能,比如一個基於Openresty的web應用
_ENV = Application "MyWeb" "v1.0.0"
__Router__"/getdata"
__Json__()
function GetData(context)
return { name = context.Request.QueryString["name"] }
end
Application 是一個類,創建MyWeb這個應用對象,綁定版本後,同時改變當前環境為自身,這樣之後在它內部定義的函數都將被認為是http請求處理方法,__Router__為它綁定路由,__Json__指定處理方式等。
因為問題是元表的特殊應用,所以,這裡就補充些一般很少被提及的用法。Lua是門非常有意思的語言,只按照最小需求提供功能,但基於元表,環境,協程能實現的東西就很多了,不過lua各版本的分裂情況,特別5.2開始始用_ENV控制環境的確讓人有點頭疼。
自從見到元表,我至今都對metaxxx感到莫名的神奇以至於理解不能,我想靜靜……
推薦閱讀: