lua-users home
lua-l archive

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


Note also that the same extended syntax can be used to serialize as well the metatable: just consider that the metatable is the value assigned to the (reserved) nil key !
So: 
  {nil={}}
builds an empty table and associates its metatable to another empty table. The metatable can also reference the main table itself as in:
  {:local t={nil=t}},
which creates a table containing (at the implied index [1]) an empty table (locally named "t") whose metatable (indicated by "nil=t") is this same table "t".
Then you can drop the outer table using the key [1] where it was implicitly stored as a value:
  {:local t={nil=t}}[1]
returns just the table t itself with its metatable set to itself.

If you don't like the idea of using "nil" to reference the metatable, another alternative is to use ":" just after the table closure to specify the metatable:
So:
  {}:{}
is the equivalent to the first solution, and
  {:local t={}:t},
is the equivalent of the second solution, and
  {:local t={}:t}[1]
is the equivalent to the third solution.

Note that the (local) "t" variable is instanciated immediately (and set immediately in the internal table of scopes used during the construction) to reference the given value in construction (if this value is a table, its internal keys have not been enumerated and assigned a value, and as well its metatable is still nil, until we assign its value with the ":" that immediately follows the "}" and which can use directly the value kept in that variable "t".

If you prefer not having to use the "local" keyword and want local scopes to be the default, external scopes using another syntax, the second solution can also be written as:
  {:t={nil=t}},
or without using the "nil" pseudo key for the metatable:
  {:t={}:t},
The third solution as well can be written as:
  {:t={nil=t}}[1]
or
  {:t={}:t}[1]

For assigning variables with external scopes, e.g. an table contains an inner table (which internally defines a table "b"), and the table "b", something like:
  x =  {[:b], {[:*b]={}}, b}[1]
* the scope of "b" is the outer table in which it is defined locally (but does not generate any key/value pair in the outer table in construction), but then it is assigned the reference to the innermost table.
* what you get from this _expression_ is a table x such that x[2] = {}, and x[1] = {x[2]}.
* there's NOTHING in the table x (or its metatable which is nil here) that still contains the name "b" used only during its construction.



Le dim. 4 nov. 2018 à 22:07, Coda Highland <chighland@gmail.com> a écrit :


On Sun, Nov 4, 2018, 1:28 PM Dirk Laurie <dirk.laurie@gmail.com wrote:
> {                                           -- starts a new local context (closure)
>  [:      ref0 = 'k1'] = :      ref1 = v1,   -- ['k1'] = v1   and set external ref0 = 'k1'
>  [:      ref2]        =               v2,   -- [1]    = v2   and set local    ref2 = 1
>  [:local ref3]        =               v3,   -- [2]    = v3   and set local    ref3 = 2
>  [:local ref4 = 'k2'] = :local ref5 = v4,   -- ['k2'] = v4   and set local    ref4 = 'k2', local    ref5 = v4
>  [:local ref6 = 'k3'] = :      ref7 = v5,   -- ['k3'] = v5   and set local    ref6 = 'k2', external ref7 = v5
>                  k4   =               ref0, -- ['k4'] = 'k1'
>  [              'k5'] =               ref2, -- ['k5'] = v2
>                                       ref1, -- [3]    = v1
> }                                           -- close the local context

Why is this better than writing it out in plain Lua that everyome can
already understand?

I understand the intent is that it can express internal references (possibly circular) in a single literal instead of having to write the plain object and then imperatively link in the references using subsequent statements.

This could be implemented by a preprocessor that translates it into an IIFE that does exactly that.

/s/ Adam