I believe that GLOBAL const variables would be much more useful.
Let's introduce both const
local variables and const
table fields.
Example:
local a = 1 -- variable "a" is defined as usual variable
a = 2 -- OK
a := 3 -- "assign forever" operator, variable "a" is const now
a = 4 -- run-time error
a := 5 -- run-time error
local b := 6 -- "b" is defined as const, the compiler does see it
b = 7 -- compile-time error
b := 8 -- compile-time error
local t = {x := 9}
t.x = 10 -- run-time error (the field "x" is a const)
t = {x := 10} -- OK, because the variable "t" was not a const
t := {x := 11} -- both "t" and its field "x" are const
t.x = 12 -- run-time error
t = {x := 12} -- run-time error
math.pi = 3 -- run-time error ("pi" is a const field in math)
_VERSION = 0x54 -- run-time error ("_VERSION" is a const field in _ENV)
t.fuck := nil -- to prohibit adding obscene field to this table
Benefits:
(1) One syntax for both const local varables and const table fields.
(2) Nice possibility to mark variable const in the middle of its lifetime.
(3) Compile-time error whenever possible, otherwise run-time error.
(4) No need to use ugly/debatable syntax like <const>, @const, @(const) or (@const)
(5) No need to introduce new keywords
Bonus:
(6) We can use more simple syntax to mark to-be-closed variables (wrap them in parentheses),
so the decision about introducing of annotation-like things to Lua could be postponed until Lua 5.5
Example:
local pi, (resource) := 4*math.atan(1), setmetatable(obj, {__release=...})
local (file) = io.open(...) -- compile-time error, resource's definition must use ":="
Drawbacks:
(-1) Every local variable should store one additional bit of run-time data.
(-2) Every Lua table should store one additional bit for each key.
(-3) You have to explicitly specify keys for const fields:
local arr = {[1] := "one", [2] := "two"} -- not nice
(-4) To be able to clone a table preserving all constant fields,
some standard Lua functions/metamethods should be modified:
-- "is_const" is boolean
local value, is_const = rawget(t, key)
rawset(t, key, value, is_const) -- this function couldn't unconst a field
for key, value, is_const in pairs(t) do
for key, value, is_const in ipairs(t) do
function __newindex(t, key, value, is_const)