lua5.4 beta中的to-be-closed变量的用法

对应目前最新lua5.4 beta版本:2019-10-09发布

这个功能之前修改过两次语法,当前的语法不出意外将会是最终决定了,目前还没有最新的中文资料,所以我来这里发一下。

先介绍下这个功能:

被标记为to-be-closed的局部变量,会在超出它的作用域时,调用它的__closed元方法,这就为我们提供了类似C++析构函数的作用。

所以一个被标记为to-be-closed的变量应该符合两个前提条件:

1、它是一个table

2、已经为它指定了__close元方法

当前版本语法:在变量名后添加<close>,将变量标记为to-be-closed变量

local t<close> = ...

示例:

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的天坑无法改变的时候,就晚了。

posted @ 2019-10-25 11:45  babypapa  阅读(880)  评论(0编辑  收藏  举报