Skip to content

Proposal: Signals #1

@Keyslam

Description

@Keyslam

Proposal: Signals

Signals provide a reactive programming system that automatically updates when data changes. The system includes three main types of signals: Signal, Computed, and Effect. Each signal can be a source of data, a consumer of data, or both, allowing data to flow in one direction and update automatically.
Signals will form the basis of 'props' for UI elements.

Code example:

-- Create a source signal for a counter
local counter = Signal(0)

-- Create a computed signal that depends on the counter
local doubled = Computed(function()
    return counter() * 2
end)

-- Create another computed signal that depends on both signals
local isEven = Computed(function()
    return doubled() % 2 == 0
end)

-- Create an effect that runs whenever any of its dependencies change
Effect(function()
    print(string.format(
        "Counter: %d, Doubled: %d, Is Even: %s",
        counter()
        doubled()
        isEven() and "Yes" or "No"
    ))
end)

-- Update the counter, which will automatically update all dependent signals
counter:set(5)  -- Prints: Counter: 5, Doubled: 10, Is Even: Yes
counter:set(3)  -- Prints: Counter: 3, Doubled: 6, Is Even: Yes
counter:set(7)  -- Prints: Counter: 7, Doubled: 14, Is Even: Yes

API

Signal

Creates a source signal that can be manually updated.

Signal(initialValue: any): Signal

Methods:

  • signal(): any / signal:get(): any
    • Returns the current value of the signal
  • signal:set(newValue: prev): void
    • Sets the signal's value
  • signal:update(fn: (curr: any) => any): void
    • Updates the signal's value with the result of the function, passing in the current value

Computed

Creates a computed signal that automatically updates based on its dependencies.

Computed signals are lazy - they only compute their value when accessed

Computed(fn: () => any): ComputedSignal

Methods:

  • signal(): any / signal:get(): any
    • Returns the current value of the signal

Effect

Creates an effect that runs whenever its dependencies change.

Effect(fn: () => void): EffectSignal

Methods:

  • effect:destroy() -> void
    • Destroys the signal

Notes

  • All signals automatically track their dependencies when accessed
    • Dependencies may change over time; when one signal is accessed conditionally based on another signal
  • Updates propagate in one direction only, preventing circular dependencies
  • Effects run synchronously when their dependencies change

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalPropose a change to the library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions