I would favor the "!" prefix because it would be very easy to type. the "!" would be followed by a keyword reserved by the language, or even no keyword at all for "indexing" the metatable field of objects.
So "t[!]" would be valid and would replace "getmetatable(t)".
* "t[!].x = 1" would replace "if not getmetatable(t) then setmetatable(t,{}) end; getmetatable(t).x=1"
* "t[!][10] = 1"
would replace "if not getmetatable(t) then setmetatable(t,{}) end; getmetatable(t)[10]=1"
* "t = { 10, x = 12; != {'a'} }" would replace
"t = {10, x = 12}; setmetatable(t, {'a'})" in table constructors (note: "!=" is still parsed as if it was two lexical units "!" and "=", a space is still allowed between them, even if "!=" is a today distinct lexical item also used as a binary operator of the language, but without any syntaxic ambiguity here)
[ C++ has made some compromizes with "<<" and ">>" for the notation of parameters of templates, but in some cases you need an extra space between the "<<" and ">>" to avoid the ambiguity with binary shift operators in expressions: this use of "<<" and ">>" for template parameters seriously complicates C++ syntaxic parsers, as the syntax is not context-free and requires backtracking: C++ is not a pure LALR or LR(n) language: try parsing C++ with a simple tool like Yacc or Bison, it does not work without complex error tracking and lot of shift-reduce ambiguities to solve, making the syntax very hard to maintain for very basic evolutions. ]
And we can declare the table constant as well (i.e. its member list is not extensible): "
t =
!const{ 10, x = 12 }
Or we can protect some members from being changed:
"t =
{
!const 0, x = 12 }" to protect the member at index [1]
As well named members can be seen as variables:
"t =
{
0,
!const
x = 12 }"
And so we can also declare constant variables:
"!const t =
{
0,
!const
x = 12 }" (where "!const" replaces the "local" keyword)
Other "!keywords" can be defined at any time in newer versions of Lua without breaking existing Lua programs.