lua-users home
lua-l archive

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


A new syntax:
   with white-list-of-names do
      ....
   end
This statement makes all names from the outer scope (with exception of white-listed names) invisible in the inner block.
The statement works for all names independently of what a name is: local/upvalue/global.

Usage example:

   local upv1, upv2 = 111, 222
   local function f()
      local x1, x2 = 11, 22
      with x1, upv1, print do -- hide all outer names except listed here
         print(x1)            -> 11
         print(x2)            -- compile-time error: "x2" is not defined
         print(upv1)          -> 111
         print(upv2)          -- compile-time error: "upv2" is not defined
         print(math.pi)       -- compile-time error: "math" is not defined
         with x1 do           -- nested "with" statement
            x1 = x1 + 1       -- OK
            print(x1)         -- compile-time error: "print" is not defined
         end
      end
      print(x2)               -> 22  (beyond the "with")
   end


Idiom for complete isolation (white-list is empty):

   with do
      -- all outer locals, upvalues and globals are inaccessible here
   end


The white-list must contain only visible names, otherwise compilation error is raised.

   local x
   with a, b, c do  -- OK: varibles a,b,c are not defined, but all globals are visible at this line
      -- "x" is invisible here (neither local not global) because "x" wasn't white-listed
      with x do     -- compile-time error: "x" is not defined
         -- "x" is invisible here because inner "with" can't unhide a name hidden by outer "with"
      end
   end


You can cache/decache globals in the outer scope without warying about the rest of the code
(because the "with" statement doesn't make a distinction between locals/upvalues/globals):

   local print = print  -- you may include or exclude this line
   with print do        -- this statement works correctly independently of whether "print" is global, local or upvalue
      print(42)
   end


Sergey Kovalev complained recently about lack of syntax for defining "pure functions" in Lua.
Due to "with" statement we could define them easily (3 variants):

   Variant #1

      local function pure_func(x, y)
         with x, y do    -- if the function must be recursive, add its name to this white-list
            -- all upvalues and globals are inaccessible here
            ...
         end
      end

   Variant#2

      local pure_func
      with pure_func do  -- we need to include something in the white-list to be able to pass the constructed function value outside the block
         function pure_func(x, y)
            -- all upvalues and globals are inaccessible here
            ...
         end
      end

   Variant#3

      with do      -- white-list is empty, the function value is passed outside the block by "return" statement
         local function pure_func(x, y)
            -- all upvalues and globals are inaccessible here
            ...
         end
         return pure_func
      end


How "with" statement should work with "_ENV" name:
1) If "_ENV" is written explicitly (user wants to directly access the upvalue "_ENV") then such "_ENV" is visible only if it's in white-list.
2) If "_ENV" is used implicitly (user accesses global variable "var", and the preprocessor replaces "var" with "_ENV.var") then this implicit "_ENV" is always accessible, even when "_ENV" is not white-listed.


Some time ago I complained about lack of Lua syntax for solving typo-in-local problem (I suggested "$" and "\" prefixes for globals).
Due to "with" statement we could write code with strict control of globals usage:

   with _ENV do
      -- all outer locals and upvalues (except _ENV) are inaccessible here
      -- global variables can be accessed only as "_ENV.varname"
   end

This solves the "typo-in-local problem": a typo would raise a compile-time error.



I believe the identifier "with" is used not very frequently in Lua programs because it is not a noun/adjective/verb,
so there would be not very much old Lua code broken by introducing this new keyword.