⚡ Àjọṣe - Reactive Relationships

Signal-based reactivity with automatic dependency tracking

What is Àjọṣe?

Àjọṣe (Yoruba: "relationship") is Ifá-Lang's reactive programming engine. It enables automatic updates when data changes, similar to SolidJS or Vue's Composition API.

📡 Signal

Reactive primitive that holds a value and notifies subscribers on change

🔄 Computed

Derived value that auto-updates when dependencies change

💥 Effect

Side-effect that runs when tracked signals change

Signals

Signal.new(value) / Ami.tuntun(iye)

Create a reactive signal with an initial value.

// Create signals
ayanmo count = Signal.new(0);
ayanmo name = Ami.tuntun("Ifá");

// Read value
Irosu.fo(count.get());  // 0

// Update value (triggers subscribers)
count.set(5);
count.update(|n| n + 1);  // Now 6

signal.subscribe(callback)

Register a callback to run when the signal changes.

ayanmo temperature = Signal.new(20);

// Subscribe to changes
temperature.subscribe(|temp| {
    Irosu.fo("Temperature changed to: " + temp);
});

temperature.set(25);  // Prints: "Temperature changed to: 25"

Computed Values

Computed.from(signals, fn)

Create a derived value that auto-updates when source signals change.

ayanmo firstName = Signal.new("Ọba");
ayanmo lastName = Signal.new("Adé");

// Computed full name
ayanmo fullName = Computed.from([firstName, lastName], || {
    padapọ firstName.get() + " " + lastName.get()
});

Irosu.fo(fullName.get());  // "Ọba Adé"

lastName.set("Olúwọlé");
Irosu.fo(fullName.get());  // "Ọba Olúwọlé" (auto-updated!)

Effects

Effect.create(fn) / Ipa.da(iṣẹ)

Run side-effects when tracked signals change.

ayanmo price = Signal.new(100);
ayanmo quantity = Signal.new(2);

// Effect: log total whenever price or quantity changes
Effect.create(|| {
    ayanmo total = price.get() * quantity.get();
    Irosu.fo("Total: $" + total);
});

// Changing either triggers the effect
quantity.set(5);  // Prints: "Total: $500"

Batching Updates

batch(fn)

Group multiple signal updates to trigger effects only once.

ayanmo x = Signal.new(0);
ayanmo y = Signal.new(0);

Effect.create(|| {
    Irosu.fo("Position: (" + x.get() + ", " + y.get() + ")");
});

// Without batch: effect runs twice
// With batch: effect runs once
batch(|| {
    x.set(10);
    y.set(20);
});
// Prints: "Position: (10, 20)" only once

Use Cases