table - Maple Programming Help

table

 weak
 create a weak table

 Calling Sequence table[weak](...) table[weak_key](...) table[weak_value](...)

Description

 • An entry in a weak table will automatically be removed when the key and/or value is no longer in use.
 • An entry in a weak_key table will be kept alive as long as something else in the system refers to the same key expression.  More specifically, an entry will be removed from a weak_key table if any of the following conditions are true:
 – The key is a small integer
 – The key is a sequence and contains one or more objects that are not in use
 – The key is a sequence and contains only small integers
 – The key is not a sequence is not in use
 • An entry in a weak_value table will be kept alive as long as something else in the system refers to the same entry expression.  More specifically, an entry will be removed from a weak_value table if any of the following conditions are true:
 – The value is a small integer
 – The value is not in use
 • The third kind of weak table incorporates both of the above conditions, and is constructed via table['weak'](...).  Index/entry pairs will be discarded when both the weak_key and weak_value criteria are satisfied.  That is, the key/value pair will remain in the table as long as either the key or value is in use somewhere else in the system.
 • The key conditions treat a sequence specially because of the way indexing is implemented in Maple.  When you index T[X,Y], a temporary (X,Y) sequence is created behind the scenes.  This (X,Y) pair is not likely to be referred to anywhere else, so the pair itself not being in use is not part of the criteria for discarding the entry.  On the other hand, when you insert T[i] := (X,Y) it is more explicit, and the entire assigned entry alone is considered.
 • Maple represents small integers as hardware-integer references, which do not require an object header or extra memory allocation to wrap them.  Therefore they are not tracked by the garbage collector, and it cannot be determined whether they are in use or not somewhere else in the system.  For this reason, small integers are considered as not in use for the purpose of determining whether a key or value should be discarded from a weak table.  On 64-bit systems, a "small integer" in this context is one that is in the range -2^62+1 .. 2^62-1.  On 32-bit systems, the range is -2^30+1 .. 2^30-1.
 • It can be difficult to predict when a particular entry will have no other references to it in Maple's memory space.  References could be held by ditto, in a remember table, on the stack, or may be conservatively kept alive because there happens to be a matching bit-pattern in the heap that Maple walks.  Weak references will only be discarded after a garbage collection sweep.
 • A weak table will behave exactly like a regular table in every way -- creation, indexing, and operations.  A weak table, in fact, is a regular table, except that after garbage collection, it is inspected to clean up references that are no longer in use.

 • The table[weak] command is thread-safe as of Maple 2019.

Examples

 > $\mathrm{alive}≔{z}^{2}$
 ${\mathrm{alive}}{≔}{{z}}^{{2}}$ (1)
 > $T≔{\mathrm{table}}_{\mathrm{weak_key}}\left(\left\{1={x}^{2},{z}^{2}=2\right\}\right)$
 ${T}{≔}{table}{}\left(\left[{1}{=}{{x}}^{{2}}{,}{{z}}^{{2}}{=}{2}\right]\right)$ (2)
 > ${T}_{1}$
 ${{x}}^{{2}}$ (3)
 > ${T}_{{z}^{2}}$
 ${2}$ (4)

Do some other things, then trigger a collection

 > $1:$$2:$$3:$$∫\frac{1}{{\left({x}^{4}-1\right)}^{2}}\phantom{\rule[-0.0ex]{0.3em}{0.0ex}}ⅆx:$
 > $\mathrm{gc}\left(\right)$

The T entry has been removed.  The T[z^2] entry's key is referenced in the variable alive, so it stays in the table.

 > $\left[\mathrm{entries}\left(T,'\mathrm{pairs}'\right)\right]$
 $\left[{{z}}^{{2}}{=}{2}\right]$ (5)

Because table indexing can return unevaluated, it is a common pattern in code to do something like this:

 > $\mathbf{if}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{assigned}\left({T}_{i}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{then}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{val}≔{T}_{i}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{end if}:$

With weak-tables, the entry at T[i] could disappear between the assigned() check and the fetch to assign to val, possibly leading to strange and hard to reproduce errors.  There are several ways to safely work around this.

Pattern#1: check assigned and get the value all at once:

 > $\mathbf{if}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{assigned}\left({T}_{i},'\mathrm{val}'\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{then}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{end if}:$

Pattern#2: compare against evaln

 > $\mathrm{val}≔{T}_{i}:$$\mathbf{if}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{val}\ne \mathrm{evaln}\left({T}_{i}\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{then}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{end if}:$

Pattern#3: use a sparse table

 > $T≔{\mathrm{table}}_{\mathrm{weak_key}}\left(\mathrm{sparse}=\mathrm{_NOTFOUND}\right):$
 > $\mathrm{val}≔{T}_{i}:$
 > $\mathbf{if}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{val}\ne \mathrm{_NOTFOUND}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{then}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{end if}:$

Pattern#4: check that the value is an expected type

 > $\mathrm{val}≔{T}_{i}:$
 > $\mathbf{if}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathrm{val}::\left(\mathrm{Not}\left(\mathrm{indexed}\right)\right)\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{then}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\phantom{\rule[-0.0ex]{0.5em}{0.0ex}}\mathbf{end if}:$

Compatibility

 • The table[weak] command was introduced in Maple 2019.