lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On Mon, Jul 8, 2019 at 7:14 AM Sergey Kovalev <kovserg33@gmail.com> wrote:
function for_scope(body)
    local list,res={}
    local function auto(close,msg)
        return function(t)
            if type(t)~='table' then error("need table: { _expression_ }",2) end
            if t[1] then table.insert(list,{ arg=t[1], fn=close or io.close })
            else
                if msg=='weak' then return table.unpack(t) end
                error(msg or t[2] or "no resource",2)
            end
            return table.unpack(t)
        end
    end
    local function defer(fn) auto(fn){true} end
    local ok,err=pcall(function() res={body(auto,defer)} end)
    for i=#list,1,-1 do list[i].fn(list[i].arg) end
    if not ok then
        if type(err)~='string' then error(err,2)
        else error("scope error\nlua: "..err,2) end
    end
    if #res>0 then return res end
end

function test()
  for t in for_scope,function(auto,defer) -- scope.begin
    local f,err=auto(io.close,"weak") { io.open "test2.txt" }
    print(f,err)
    defer(function() print "defer" end)
    return auto(){ io.open "readme.txt" }:read()
  end do return table.unpack(t) end -- scope.end
end
print(test())



Yes, you can do without "local <toclose>", but I would not call your example readable code. The point of adding features like this to a language is to make programs simpler and easier to understand by increasing the expressive power of the language.

This is a whole lot more readable:

local <toclose> f = assert(io.open("test.txt", "r"))
-- do something with f
return value

I think the "<toclose>" facility is a fair tradeoff between added language complexity and expressive power. It's also likely to be much faster because there's no need to create closures, no need to pack or unpack parameter lists, and no need to use 'pcall' or forward the error.


-- 
--