lua-users home
lua-l archive

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


Fix below:
Le mer. 22 juil. 2020 à 05:19, Philippe Verdy <verdyp@gmail.com> a écrit :
       if ({false, [1] = true})[1] then
             return 'LuaJIT' 
Is the order of evaluation of table constructors really specified now (i.e. the order of evaluation of keys expressions, and values expressions, and then the order of assignment) ?

And are all these evaluations interleaved (i.e. evaluate the first key, then the first value, then assign, then restart with the next key/value pair) or separated (all keys first, then all values, then all assignments)?

Or mixed: i.e. keys and values evaluation interleaved, and stored in a single temporary sequence (then used to create the constructor)? As if the code for
   t = {ident(1) = ident(false), ident(2) = ident(true), ident(3) = ident('other')}
 was:
   __kv= {ident(1), ident(false), ident(2), ident(true), ident(3), ident('other')}
   t = __convertkeyvalues(__kv)
which should also print:
(Fixed): 
   ident:1
   ident: false
   ident:1
   ident: true
   ident:2
   ident: other

in that order, for the evaluation of each key and value before the actual storage in the final array, and that would also assign values in t in the ascending sequence in _kv (the last keys overwriting the value used in any prior key).
Note that I cannot print the order of assignation, as there's no way to assign a metatable to a table that is still not constructed to inspect the behavior of "__newindex", all we can do is to check the result to see which value was assigned to a given key. Lua still has no syntaxic way to create a metatable with a constructor using metamethods for its assignments. But the result is still unpredictable.

Even if Lua had a syntax for defining metamethod (for __newindex at least), but we could also pass a table of metamethods to the constructor, and that table would also have its own constructor and its evaluation order would also matter)!

   t = {
      __newindex = function(t, k, v) print('new t['..tostring(k)..']='..tostring(v)); t|k] = v; end
   } :: {ident(1) = ident(false), ident(2) = ident(true), ident(3) = ident('other')}

Change the syntax by writing the metatable construction after the main table construction should not be different:

   t = {ident(1) = ident(false), ident(2) = ident(true), ident(3) = ident('other')} ::  {
      __newindex = function(t, k, v) print('new t['..tostring(k)..']='..tostring(v)); t|k] = v; end
   }

Here I would expect the metatable to be fully built before building the actual table assigned to t.

Then the table constructor can also create the initial table because it knows the (even) size of the ordered sequence containing all pairs/values, so it can predict a default size for the final table, even if the ordered sequence contains some duplicate keys (but note that the sequence may also contain nil values, so this is still not a pure sequence even if it's ordered).

Anyway I'm not even sure that the table constructor uses __newindex for its table constructors, it may just use rawset(t, k, v) which is untrackable (except by using a debugging core library and loading it before the Lua engine is loaded, meaning that the result is unpredicatable in that case).