對應目前最新lua5.4 beta版本:2019-10-09發佈html
這個功能以前修改過兩次語法,當前的語法不出意外將會是最終決定了,目前尚未最新的中文資料,因此我來這裏發一下。c++
先介紹下這個功能:函數
被標記爲to-be-closed的局部變量,會在超出它的做用域時,調用它的__closed元方法,這就爲咱們提供了相似C++析構函數的做用。lua
因此一個被標記爲to-be-closed的變量應該符合兩個前提條件:spa
一、它是一個table設計
二、已經爲它指定了__close元方法code
當前版本語法:在變量名後添加<close>,將變量標記爲to-be-closed變量htm
local t<close> = ...blog
示例:作用域
function test2() local t = {x=1}; setmetatable(t, {__close=function(...) print('close') end}); local tc<close> = t; --函數返回時,將自動執行tc的__close元方法。 end test2(); -- 以文件操做爲例: -- 在沒有to-be-closed變量的狀況下: function foo() -- 打開一個文件 local fd = io.open('c:\\1.txt', 'r'); -- 讀取文件 local x = fd:read('*a'); -- 接下來就是對文件內容進行判斷 -- 假如咱們在邏輯上須要多種內容 if x == '1' then fd:close(); return; else if x == '2' then print('文件內容爲:2'); fd:close(); return; end print('錯誤的文件內容:'..x); fd:close(); end -- to-be-closed的狀況下: function foo2() -- 在變量名以後添加<close> local fd<close> = io.open('c:\\1.txt', 'r'); -- 接下來就和 各類返回位置都要寫的超級煩人的fd:close()說再見 -- 讀取文件 local x = fd:read('*a'); if x == '1' then return; else if x == '2' then print('文件內容爲:2'); return; end print('錯誤的文件內容:'..x); end -- 以實現c++的std::lock_guard爲例: -- xshare.lock xshare.unlock來自於個人另外一篇文章:https://www.cnblogs.com/babypapa/p/11711389.html function lock_guard(xt) local t = {xstab = xt}; setmetatable(t, {__close=function(tab) xshare.unlock(tab.xstab) end}) xshare.lock(xt); return t; end function foo3(xt) local lg<close> = lock_guard(xt); ... end
而後,下面是吐槽
我只能說,羅伯託老兄不知道是在什麼狀況下的考慮,而設計出這種東西的,這絕對是思惟掉坑了。
若是隻考慮元方法,你偷懶就偷懶了,用表來實現,是能夠理解的。
但使用了新的語法時,再依賴過去的元方法,就關係就混亂了,
語法是什麼?更底層的東西。
而元方法的實現,首先暴露給用戶的入口點就是一個函數。
而後很顯然,底層依賴上層的關係出現了。
再來看同期的產物,const變量,只有local v<const> = ...這樣的方式,而且它不做用於table內部。local t<const> = {a=1, b = 2}; t.a=11照樣能夠改。
當一個const變量,只能本地儲存的時候,咱們爲什麼還要脫褲子放屁,我感受,怕不是我本身對常量的定義有本質的誤解。
我就想說,把const設計成一個函數很差嗎?
local a, b, c = const(1, 2,3)
x,y,z = const(1,2,3)
local t = const({const(1, 2, 3)})
t = {const(1), 2, const(3)}
這種方式不比<const>容易實現,不能更容易知足你們的需求?
最後我想說,若是再繼續偷懶,等到哪一天,這些問題被用戶習慣掉以後,就像nil的天坑沒法改變的時候,就晚了。