Skip to main content

Silo

A Silo is a state container, inspired by Redux slices and designed for Roblox developers.

Types

State<S>

type State<S> = {[string]any}

Represents state.

Modifier<S>

type Modifier<S> = (
State<S>,
any
) → ()

A function that modifies state.

Action<A>

interface Action<A> {
Namestring
PayloadA
}

Actions are passed to Dispatch. However, typically actions are never constructed by hand. Use a silo's Actions table to generate these actions.

Functions

new

Silo.new(
defaultStateState<S>,
modifiers{[string]Modifier<S>}?
) → Silo

Create a Silo.

local statsSilo = Silo.new({
	-- Initial state:
	Kills = 0,
	Deaths = 0,
	Points = 0,
}, {
	-- Modifiers are functions that modify the state:
	SetKills = function(state, kills)
		state.Kills = kills
	end,
	AddPoints = function(state, points)
		state.Points += points
	end,
})

-- Use Actions to modify the state:
statsSilo:Dispatch(statsSilo.Actions.SetKills(10))

-- Use GetState to get the current state:
print("Kills", statsSilo:GetState().Kills)

From the above example, note how the modifier functions were transformed into functions that can be called from Actions with just the single payload (no need to pass state). The SetKills modifier is then used as the SetKills action to be dispatched.

combine

Silo.combine(
silos{Silo},
initialStateState<S>?
) → Silo

Constructs a new silo as a combination of other silos.

GetState

Silo:GetState() → State<S>

Get the current state.

local state = silo:GetState()

Dispatch

Silo:Dispatch(actionAction<A>) → ()

Dispatch an action.

silo:Dispatch(silo.Actions.DoSomething("something"))

Subscribe

Silo:Subscribe(subscriber(
newStateState<S>,
oldStateState<S>
) → ()) → () → ()

Subscribe a function to receive all state updates, including initial state (subscriber is called immediately).

Returns an unsubscribe function. Call the function to unsubscribe.

local unsubscribe = silo:Subscribe(function(newState, oldState)
	-- Do something
end)

-- Later on, if desired, disconnect the subscription by calling unsubscribe:
unsubscribe()

Watch

Silo:Watch(
selector(State<S>) → T,
onChange(T) → ()
) → () → ()

Watch a specific value within the state, which is selected by the selector function. The initial value, and any subsequent changes grabbed by the selector, will be passed to the onChange function.

Just like Subscribe, a function is returned that can be used to unsubscribe (i.e. stop watching).

local function SelectPoints(state)
	return state.Statistics.Points
end

local unsubscribe = silo:Watch(SelectPoints, function(points)
	print("Points", points)
end)

ResetToDefaultState

Silo:ResetToDefaultState() → ()

Reset the state to the default state that was given in the constructor.

local silo = Silo.new({
	Points = 0,
}, {
	SetPoints = function(state, points)
		state.Points = points
	end
})

silo:Dispatch(silo.Actions.SetPoints(10))

print(silo:GetState().Points) -- 10

silo:ResetToDefaultState()

print(silo:GetState().Points) -- 0
Show raw api
{
    "functions": [
        {
            "name": "new",
            "desc": "Create a Silo.\n\n```lua\nlocal statsSilo = Silo.new({\n\t-- Initial state:\n\tKills = 0,\n\tDeaths = 0,\n\tPoints = 0,\n}, {\n\t-- Modifiers are functions that modify the state:\n\tSetKills = function(state, kills)\n\t\tstate.Kills = kills\n\tend,\n\tAddPoints = function(state, points)\n\t\tstate.Points += points\n\tend,\n})\n\n-- Use Actions to modify the state:\nstatsSilo:Dispatch(statsSilo.Actions.SetKills(10))\n\n-- Use GetState to get the current state:\nprint(\"Kills\", statsSilo:GetState().Kills)\n```\n\nFrom the above example, note how the modifier functions were transformed\ninto functions that can be called from `Actions` with just the single\npayload (no need to pass state). The `SetKills` modifier is then used\nas the `SetKills` action to be dispatched.",
            "params": [
                {
                    "name": "defaultState",
                    "desc": "",
                    "lua_type": "State<S>"
                },
                {
                    "name": "modifiers",
                    "desc": "",
                    "lua_type": "{ [string]: Modifier<S> }?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Silo"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 86,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "combine",
            "desc": "Constructs a new silo as a combination of other silos.",
            "params": [
                {
                    "name": "silos",
                    "desc": "",
                    "lua_type": "{Silo}"
                },
                {
                    "name": "initialState",
                    "desc": "",
                    "lua_type": "State<S>?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Silo"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 126,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "GetState",
            "desc": "Get the current state.\n\n```lua\nlocal state = silo:GetState()\n```",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "State<S>\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 177,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "Dispatch",
            "desc": "Dispatch an action.\n\n```lua\nsilo:Dispatch(silo.Actions.DoSomething(\"something\"))\n```",
            "params": [
                {
                    "name": "action",
                    "desc": "",
                    "lua_type": "Action<A>"
                }
            ],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 191,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "Subscribe",
            "desc": "Subscribe a function to receive all state updates, including\ninitial state (subscriber is called immediately).\n\nReturns an unsubscribe function. Call the function to unsubscribe.\n\n```lua\nlocal unsubscribe = silo:Subscribe(function(newState, oldState)\n\t-- Do something\nend)\n\n-- Later on, if desired, disconnect the subscription by calling unsubscribe:\nunsubscribe()\n```",
            "params": [
                {
                    "name": "subscriber",
                    "desc": "",
                    "lua_type": "(newState: State<S>, oldState: State<S>) -> ()"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "() -> ()\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 235,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "Watch",
            "desc": "Watch a specific value within the state, which is selected by the\n`selector` function. The initial value, and any subsequent changes\ngrabbed by the selector, will be passed to the `onChange` function.\n\nJust like `Subscribe`, a function is returned that can be used\nto unsubscribe (i.e. stop watching).\n\n```lua\nlocal function SelectPoints(state)\n\treturn state.Statistics.Points\nend\n\nlocal unsubscribe = silo:Watch(SelectPoints, function(points)\n\tprint(\"Points\", points)\nend)\n```",
            "params": [
                {
                    "name": "selector",
                    "desc": "",
                    "lua_type": "(State<S>) -> T"
                },
                {
                    "name": "onChange",
                    "desc": "",
                    "lua_type": "(T) -> ()"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "() -> ()\n"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 276,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "ResetToDefaultState",
            "desc": "Reset the state to the default state that was given in the constructor.\n\n```lua\nlocal silo = Silo.new({\n\tPoints = 0,\n}, {\n\tSetPoints = function(state, points)\n\t\tstate.Points = points\n\tend\n})\n\nsilo:Dispatch(silo.Actions.SetPoints(10))\n\nprint(silo:GetState().Points) -- 10\n\nsilo:ResetToDefaultState()\n\nprint(silo:GetState().Points) -- 0\n```",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 315,
                "path": "modules/silo/init.lua"
            }
        }
    ],
    "properties": [],
    "types": [
        {
            "name": "State<S>",
            "desc": "Represents state.",
            "lua_type": "{[string]: any}",
            "source": {
                "line": 10,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "Modifier<S>",
            "desc": "A function that modifies state.",
            "lua_type": "(State<S>, any) -> ()",
            "source": {
                "line": 17,
                "path": "modules/silo/init.lua"
            }
        },
        {
            "name": "Action<A>",
            "desc": "Actions are passed to `Dispatch`. However, typically actions are\nnever constructed by hand. Use a silo's Actions table to generate\nthese actions.",
            "fields": [
                {
                    "name": "Name",
                    "lua_type": "string",
                    "desc": ""
                },
                {
                    "name": "Payload",
                    "lua_type": "A",
                    "desc": ""
                }
            ],
            "source": {
                "line": 28,
                "path": "modules/silo/init.lua"
            }
        }
    ],
    "name": "Silo",
    "desc": "A Silo is a state container, inspired by Redux slices and\ndesigned for Roblox developers.",
    "source": {
        "line": 51,
        "path": "modules/silo/init.lua"
    }
}