[NoW] Why only LOCAL const variables?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[NoW] Why only LOCAL const variables?

Egor Skriptunoff-2
Why introducing only LOCAL const variables?
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)


Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Why only LOCAL const variables?

Philippe Verdy
Note that your syntax requires that all variables in the same assignment or declaration are to become "constants" or read-only at the same time which is not always wanted:
   local first, rest := ...;

One may want to set "first" as "constant" but not "rest" (whose content will still be modified). Work around:
   local first, rest = ... ; first := first;

Your proposed syntax using parentheses for "toclose" variables in local declarations or in function parameters declarations will also add new ambiguities and is very unevident. And it breaks any possibility to introduce later the annotations or other syntaxic features (that will really need parentheses exactly for the role of scoping these features and avoiding ambiguities with inner token): let's remember we still have to avoid the effect caused with implicit curification that implicitly propagates the effects of function calls.

Also I don't like the fact you forbid:
  math.pi = 3; -- run-time error ("pi" is a const field in math)

Lot of code depend on the possibility of creating a new environment from another. And you don't propose any way to cleate such derivation. But this can be solved this way:

"Locking" a field should not be blocked at all, but it should only have the effect that if you assign it, the container is duplicated in a new object (in the current lexical scope) whose field is reassigned. For the statement above this would create a new "math" value (copying all its existing field, preserving all "constant" fields except the one you reassign). Then after that statement, "math" refers to a new object, as if you had recreated it with a "local math" statement. The original "math" object is not destroyed, but just hidden and has lost one reference. So there will NOT be any runtime error.



Le mer. 12 juin 2019 à 08:34, Egor Skriptunoff <[hidden email]> a écrit :
Why introducing only LOCAL const variables?
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)