標籤:

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 Lua

class 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感到莫名的神奇以至於理解不能,我想靜靜……


推薦閱讀:

TAG:元編程 | Lua |