Computed
function Computed(callback: () -> any): Computed
Constructs and returns a new computed object, using the given callback to compute this object's values based on other state objects or computed objects.
Parameters¶
callback: () -> any
- a function which computes and returns the value to use for this computed object.
Object Methods¶
get()
¶
function Computed:get(): any
If dependencies are currently being detected (e.g. inside a computed callback), then this computed object will be used as a dependency.
Example Usage¶
local numCoins = State(50)
local doubleCoins = Computed(function()
return numCoins:get() * 2
end)
print(doubleCoins:get()) --> 100
numCoins:set(2)
print(doubleCoins:get()) --> 4
Dependency Management¶
Computed objects automatically detect dependencies used inside their callback
each time their callback runs. This means, when you use a function like :get()
on a state object, it will register that state object as a dependency:
local numCoins = State(50)
local doubleCoins = Computed(function()
-- Fusion detects we called :get() on `numCoins`, and so adds `numCoins` as
-- a dependency of this computed object.
return numCoins:get() * 2
end)
When a dependency changes value, the computed object will re-run its callback to
generate and cache the current value internally. This value is later exposed via
the :get()
method.
Something to note is that dependencies are dynamic; you can change what values your computed object depends on, and the dependencies will be updated to reduce unnecessary updates:
local stateA = State(5)
local stateB = State(5)
local selector = State("A")
local computed = Computed(function()
print("> updating computed!")
local selected = selector:get()
if selected == "A" then
return stateA:get()
elseif selected == "B" then
return stateB:get()
end
end)
print("increment state A (expect update below)")
stateA:set(stateA:get() + 1)
print("increment state B (expect no update)")
stateB:set(stateB:get() + 1)
print("switch to select B")
selector:set("B")
print("increment state A (expect no update)")
stateA:set(stateA:get() + 1)
print("increment state B (expect update below)")
stateB:set(stateB:get() + 1)
> updating computed!
increment state A (expect update below)
> updating computed!
increment state B (expect no update)
switch to select B
> updating computed!
increment state A (expect no update)
increment state B (expect update below)
> updating computed!
Danger
Stick to using state objects and computed objects inside your computations. Fusion can detect when you use these objects and listen for changes.
Fusion can't automatically detect changes when you use 'normal' variables:
local theVariable = "Hello"
local badValue = Computed(function()
-- don't do this! use state objects or computed objects in here
return "Say " .. theVariable
end)
print(badValue:get()) -- prints 'Say Hello'
theVariable = "World"
print(badValue:get()) -- still prints 'Say Hello' - that's a problem!
By using a state object here, Fusion can correctly update the computed object, because it knows we used the state object:
local theVariable = State("Hello")
local goodValue = Computed(function()
-- this is much better - Fusion can detect we used this state object!
return "Say " .. theVariable:get()
end)
print(goodValue:get()) -- prints 'Say Hello'
theVariable:set("World")
print(goodValue:get()) -- prints 'Say World'
This also applies to any functions that change on their own, like
os.clock()
. If you need to use them, store values from the function in a
state object, and update the value of that object as often as required.