Class DynamicVirtualValue
(Abstract) A container a base value and many VirtualValues which are "stacked" together.
A DynamicVirtualValue (or DVV for short) is a VirtualValue which can also have child VirtualValues added to it. Like a plain VirtualValue, a DVV still contains a value, which is called the base value (retrieved using getBase), in addition to its children.
When you get the value of a DVV, you get the stacked value instead of the base value. This is calculated from the base value and values of the children using the stack method. The calculation is as follows:
stacked_value = base_value + value1 + value2 + ... + valueN
Where valueN
indicates the value gotten from each child, and +
represents the operation defined
by the stack method. The operations are completed left-to-right. This is an O(n) calculation.
Children and Nesting
- Any VirtualValue can be added as a child, including other DVVs. During a stacked value calculation a DVV calls get on its children. For child DVVs, this returns their stacked value (not their base value).
- A VirtualValue can also be added as a child to multiple DVVs. In other words, a VirtaulValue may have any number of parents.
- Beware of disasterous non-halting infinite loops when two DVVs are decendants of each other.
Caching and "Dirtiness"
When the stacked value is calculated, it is cached so that future calls skip recalculation (providing a runtime of O(1)). However, if the DVV's base value changes or if a child is added/removed/changed, then the DVV is considered dirty. The next time the value is gotten, it will be recalculated. Furthermore, a DVV is also dirtied whenever a child DVV is dirtied.
Runtime Bewares
Understanding when the DVV is dirtied is important, as this can affect runtime. To avoid excessive recalculations, you should adjust a DVV's base value and children before you get, listen or bind, as these methods recalculate the stacked value; in the case of listen and bind, these recalculate also when DVV is dirtied). If you're making a lot of modifications to the base value or child values, disconnect the connections these functions return temporarily. When you are done making changes, re-listen or re-bind.
local dvnv = DynamicVirtualNumberValue.new("Add", 0) local conn = dvnv:listen(myFunction) -- At this point, when any dirty-ing change is made, -- the value is recalculated (an O(n) operation) -- To stop this, disconnect and forget about the old connection: conn:disconnect() conn = nil -- Now, we can make changes without causing recalculations: dvnv:set(8) dvnv:addChild(VirtualNumberValue.new(5)) dvnv:removeChild(someOtherChild) -- Re-listen once finished; this recalculates then calls myFunction: conn = dvnv:listen(myFunction) --> calls myFunction(13)
Implementations:
- DynamicVirtualNumberValue, for number
- DynamicVirtualStringValue, for string
- DynamicVirtualBoolValue, for bool
See also:
Events
DynamicVirtualValue.onChildAdded | Fires when a VirtualValue is added as a child |
DynamicVirtualValue.onChildRemoved | Fires when a child is removed |
DynamicVirtualValue.onDirtied | Fires when the base value is changed or any child is changed/dirtied, indicating the value must be recaluclated the next time it is gotten. |
Functions
DynamicVirtualValue.new(expectedType) | Constructs a new DynamicVirtualValue which contains a certain expectedType |
Metamethods
DynamicVirtualValue:__tostring() | Returns the current value passed to tostring, followed by a comma-separated list of the child values passed to tostring. |
Methods
DynamicVirtualValue:stack(_lhs, _rhs) | (Abstract) Defines how two values are "stacked" together, usually through some operation. |
DynamicVirtualValue:isDirty() | Returns whether this value is dirty and will be recalculated the next time it is gotten |
DynamicVirtualValue:getChildren() | Returns an array (numerically-indexed table) of the children. |
DynamicVirtualValue:children() | Returns an iterator function which returns each index-child pair |
DynamicVirtualValue:isChild(child) | Returns whether the given object is a child |
DynamicVirtualValue:addChild(child) | Adds the given VirtualValue as a child. |
DynamicVirtualValue:newChild(...) | Constructs a new child with the given parameters using the implementation's associated VirtualValue implementation, then adds it. |
DynamicVirtualValue:newChildren(values) | Constructs multiple new children with the table of single parameters. |
DynamicVirtualValue:addChildren(children) | Adds a table of children |
DynamicVirtualValue:getChildIndex(child) | Returns the index of the given child |
DynamicVirtualValue:removeChildAtIndex(idx) | Removes the child at the given index. |
DynamicVirtualValue:removeChild(child) | Removes the child similar to how removeChildAtIndex does |
DynamicVirtualValue:removeAllChildren() | Removes all children |
DynamicVirtualValue:getBase() | Returns the base value, which is the raw value stored by this DynamicVirtualValue. |
DynamicVirtualValue:set(newValue) | Sets the new base value |
DynamicVirtualValue:get() | Gets the stacked value, recalculating it if dirty |
DynamicVirtualValue:listen(func) | Calls func immediately with the stacked value, then again every time this value is
dirtied. |
DynamicVirtualValue:bind(object, property) | Sets object[property] to the stacked value, then again every time this value is
dirtied. |
Events
- DynamicVirtualValue.onChildAdded
-
Fires when a VirtualValue is added as a child
- child VirtualValue The child that was added
- DynamicVirtualValue.onChildRemoved
-
Fires when a child is removed
- child VirtualValue The child that was removed
- DynamicVirtualValue.onDirtied
- Fires when the base value is changed or any child is changed/dirtied, indicating the value must be recaluclated the next time it is gotten.
Functions
Methods- DynamicVirtualValue.new(expectedType)
-
Constructs a new DynamicVirtualValue which contains a certain
expectedType
Parameters:
- expectedType string expected type (or table of expected types) to be contained
Metamethods
- DynamicVirtualValue:__tostring()
-
Returns the current value passed to tostring, followed by a comma-separated
list of the child values passed to tostring.
Returns:
Methods
- DynamicVirtualValue:stack(_lhs, _rhs)
-
(Abstract) Defines how two values are "stacked" together, usually through some operation.
Parameters:
- _lhs The left-hand side of the operation
- _rhs The right-hand side of the operation
- DynamicVirtualValue:isDirty()
-
Returns whether this value is dirty and will be recalculated the next time it is gotten
Returns:
-
boolean
Whether this value is dirty
- DynamicVirtualValue:getChildren()
- Returns an array (numerically-indexed table) of the children.
- DynamicVirtualValue:children()
-
Returns an iterator function which returns each index-child pair
Usage:
for i, child in dvv:children() do ... end
- DynamicVirtualValue:isChild(child)
-
Returns whether the given object is a child
Parameters:
- child The object to query
Returns:
-
boolean
- DynamicVirtualValue:addChild(child)
-
Adds the given VirtualValue as a child. Dirties the DVV and fires onChildAdded.
When this child is changed or dirtied (for child DVVs), this DVV is dirtied.
Parameters:
- child VirtualValue The child to add
Returns:
-
number
The child's index
- DynamicVirtualValue:newChild(...)
-
Constructs a new child with the given parameters using the implementation's associated VirtualValue
implementation, then adds it.
For example, DynamicVirtualNumberValue:newChild constructs a VirtualNumberValue). The child will
be cleaned up when this value is cleaned up.
Parameters:
- ... The arguments to pass to the VirtualValue constructor
Returns:
-
The newly-constructed child
Usage:
local dvnv = DynamicVirtualNumberValue.new("Add", 3) dvnv:newChild(5)
- DynamicVirtualValue:newChildren(values)
-
Constructs multiple new children with the table of single parameters.
Parameters:
- values
Returns:
-
A table of all the newly-constructed children
- DynamicVirtualValue:addChildren(children)
-
Adds a table of children
Parameters:
- children table The children to add
- DynamicVirtualValue:getChildIndex(child)
-
Returns the index of the given child
Parameters:
- child
Returns:
-
number
The index of the child
- DynamicVirtualValue:removeChildAtIndex(idx)
-
Removes the child at the given index. Dirties the DVV and fires onChildRemoved
Parameters:
- idx number The index of the child to remove
- DynamicVirtualValue:removeChild(child)
-
Removes the child similar to how removeChildAtIndex does
Parameters:
- child
- DynamicVirtualValue:removeAllChildren()
- Removes all children
- DynamicVirtualValue:getBase()
-
Returns the base value, which is the raw value stored by this DynamicVirtualValue.
See also:
- DynamicVirtualValue:set(newValue)
-
Sets the new base value
Parameters:
- newValue The new base value
- DynamicVirtualValue:get()
-
Gets the stacked value, recalculating it if dirty
Returns:
-
The calculated stack value
- DynamicVirtualValue:listen(func)
-
Calls
func
immediately with the stacked value, then again every time this value is dirtied. As this function must get the current value each time it is dirtied, it will cause continual recalculations. This can negatively affect runtimes if you are making lots of changes while the connection is active. Therefore, it's recommended you disconnect if you're excessively dirtying the value so you don't cause needless recalculations.Parameters:
- func function The listener function
Returns:
-
Connection
When disconnected, stops
func
from being called when the value changesSee also:
- DynamicVirtualValue:bind(object, property)
-
Sets
object[property]
to the stacked value, then again every time this value is dirtied. As this function must get the current value each time it is dirtied, it will cause continual recalculations. This can negatively affect runtimes if you are making lots of changes while the connection is active. Therefore, it's recommended you disconnect if you're excessively dirtying the value so you don't cause needless recalculations.Parameters:
- object
A table, userdata, etc which can accept
[property] = ...
- property
string
The index on
object
to set
Returns:
-
Connection
When disconnected, stops
func
from being called when the DVV is dirtiedSee also:
- object
A table, userdata, etc which can accept