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.