Value semantics
This MR changes a lot in itable's internal implementation:
-
itable{a = {b = 42}}is now processed by deep copying all of the tables - Calling
itablemultiple times with the same table will always produce the same itable object until the garbage collector clears the original table. - Public API changed:
-
deepcopyremoved, useitableoritable.from -
eqremoved, use=orrawequal -
immutableremoved, useitableoritable.from -
fromadded, an alias to a directitablemodule call
-
Value semantics
In Lua, evaluating the same table literal twice will produce different objects:
> {1, 2, 3}
table: 0x56391fe3a100
> {1, 2, 3}
table: 0x56391fe3a3e0
With itable, the resulting objects will be the same:
> itable{1, 2, 3}
itable: 0x564041fe5560
> itable{1, 2, 3}
itable: 0x564041fe5560
A new object may be constructed if the garbage collector collected any older references to this data structure:
> x = itable{1, 2, 3}
> x
itable: 0x564041fe5560
> collectgarbage()
0
> itable{1, 2, 3}
itable: 0x564041fe5560
> x = nil
> collectgarbage()
0
> itable{1, 2, 3}
itable: 0x56404203af70
Because of this, testing two immutable tables for equality no longer requires deep comparison. Immutable tables can be used as keys in other tables with equally fast lookups to regular Lua data types.
Memory usage
This change can severely impact memory usage. This still needs proper measurement, but beware that to implement value semantics, all tables are serialized and interned in a weak table. The garbage collector can still collect unused objects, so the table holding interned values will not grow forever, but if a lot of tables are retained, memory usage can spike.