lua-users home
lua-l archive

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


On 09/03/16 06:06 AM, Dirk Laurie wrote:
Pascal introduced the construction

with tbl do
...
end

Inside the do block, fields of 'tbl' shadow outer variables.

This is hard to mimic exactly in Lua. Here is my attempt.

--- for _ENV in with(tbl,context) do ... end
--  * mimics Pascal `with`, i.e. not a real loop, just a do-once
--  * falls back to `context` which defaults to `_ENV`
--  * can be nested, outer level fields only visible if explicit
--  * temporarily deactivates metatable of `tbl`
local
function with(tbl,context)
   local t=tbl
   if type(t)~='table' then error("'with' expects a table, got "..type(t),2) end
   local m=getmetatable(t)
   return function()
     if t then
       t=nil
       return setmetatable(tbl,{__index=context or _ENV})
     else
       setmetatable(tbl,m)
     end
   end
end

Problem 1: Local variables defined outside the `for` stay visible.
Problem 2: I can't think of a neat way to retain the metatable of `tbl`.

Try this:

local function with(t, e)
  return setmetatable({}, {__index=function(t,k) return t[k] or e[k] end})
end

do local _ENV = with(tbl, _ENV)
  -- stuff here
end

Doesn't solve 1 but seems much nicer than the for hack. It's also simpler. It also supports non-tabke tbl/_ENV and metamethods in tbl.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.