# Making Reactive Datatypes in 200 lines of Nim

## `Sigil` becomes more than a name

[Sigils](https://github.com/elcritch/sigils) now supports first-class reactive data types! I wish I could say it was a grueling undertaking, but it wasn’t. Thanks to the core of Sigil’s being signals and slots along with Nim’s superb meta-programming it was pretty trivial to knock out. The trickiest part has been finding out what behaviors the JavaScript implementations follow.

Coincidently, [Svelte’s](https://www.infoworld.com/article/2336000/reactive-magic-in-svelte-5-understanding-runes.html) reactive datatype is called `Rune` meaning *”a mark or letter of mysterious or magic significance”* while `Sigil` means *“an inscribed or painted symbol considered to have magical power“*. Almost like this is what the Sigils library was meant to become.

I’m excited since this *neatly* solves a longstanding wart in [Figuro](https://github.com/elcritch/figuro) UIs for how to provide a nice clean and simple API for handling reactive data. Signals and slots are powerful but a bit verbose and my initial APIs left me feeling underwhelmed. Reactive datatypes are much nicer:

```ocaml
    let x = newSigil(5)
    let y = newSigil(false)
    let z = computed[int]():
      if y{}: x{} * 2 else: 0

    check x{} == 5
    check y{} == false
    check z{} == 0
    y <- true #(* update the calue in y *)
    check y{} == true
    check z{} == 10
```

Previously in Figuro I was trying to do something similar but it just wasn’t *it*:

```ruby
type Main* = ref object of Figuro
       counter = Property[int]()

proc draw*(self: Main) {.slot.} =
   withWidget(self):
      rectangle "count":
        text "btnText":
          bindProp(self.counter)
          node.setText({font: $(self.counter.value) & " ₿" }, Center, Middle)    
      Button.new "btnAdd":
        text "btnText":
          node.setText({largeFont: "–"}, Center, Middle)
        ## something like this:
        self.counter.onSignal(doClicked) do(counter: Property[int]):
          counter.update(counter.value-1)
```

This can now become more streamlined and provide a semantics familiar to webdevs (note I haven’t wired this bit into Figuro at publication time):

```ruby
type Main* = ref object of Figuro
       counter = newSigil[int](0)

proc draw*(self: Main) {.slot.} =
   withWidget(self):
      rectangle "count":
        text "btnText":
          node.setText({font: $(self.counter{}) & " ₿" }, Center, Middle)    
      Button.new "btnAdd":
        text "btnText":
          node.setText({largeFont: "–"}, Center, Middle)
        node.onSignal(doClicked):
          self.counter <- self.counter{} - 1
```

## `Sigil[T]` Villain’s Origin Story

The other day I posted on Nim-lang’s `#appdev` Discord channel about adding some animation support to [Figuro](https://github.com/elcritch/figuro). Using the new *signals and slots* from my new [Sigils](https://github.com/elcritch/sigils) made creating a new more powerful [`Fader`](https://github.com/elcritch/figuro/blob/e09cd458edb571fbd830f4d0b7854d942ab59854/src/figuro/ui/animations.nim#L7) primitive super easy.

The `Fader` Agent (Sigil’s core object) fades in or out on a linear scale and can be interrupted midway and start going the other direction. In a couple dozen lines it seamlessly computes the next step based on Figuro’s `doTick` core signal when it begins fading and disconnects itself when it’s finished. `Fader` provides a core primitive needed for many key UI operations include fading a button on hover or sliding a menu in or out.

Phil, a fellow participant in `#appdev` (aka IsoFruit), asked about reactive datatypes. Phil does a lot of webdev and apparently \*signals\* have taken over the JavaScript UI world. Given that I had just made `Fader` which is a very reactive objects, I was curious what he meant and we started discussing it. He mentioned reactive data types were becoming standard in JavaScript with them being called Observables in RxJs, Signals in Angular, and Runes in Svelte.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1738209771616/1d7a926a-8849-4532-8650-23c58e109e00.png align="center")

After some back and forth it turned out he was referring to [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming). It’s an interesting field and I wasn’t sure how it’d fit into a static language like Nim. I’d experimented with it briefly way back in 2014 (almost a decade now :wow:) to run a PID loop on a Raspberry Pi. That experiment didn’t turn out well and was one of my first forays into latency sensitive programming and dealing with the pain of GC.

Nowadays *Reactive Programming* has moved into the mainstream and the method *de jour* of handling reactive user interfaces. That’s basically *all* UIs. Here’s a short example given by Phil:

```javascript
const x = signal(5)
const double = computed(() => x()*2)
x.set(2)
// double is now 4
```

Well I figured that looks simple. I bet Figuro (really *Sigils*) could make short work of that. A short 20 minutes later I had a working example! Sorta, well behold:

```ocaml
    type
      Reactive = ref object of Agent
        value: int
    proc setValue(tp: Reactive, val: int) {.signal.}
    let
      x = Reactive(value: 5)
      y = Reactive()
    
    proc computed(self: Reactive, val: int) {.slot.} =
      self.value = val * 2
    x.connect(setValue, y, computed)

    emit x.setValue(2)
    echo "Y: ", y.value
```

This was lacking some syntactic sugar, but proved to me that it could be done. The next day I added a couple of `template`'s and got:

```ocaml
  test "reactive wrapper":
    let
      x = reactive(5)
      y = computed(x): # probably need a macro to get rid of the extra x
        2 * x{}

    x <- 2
    echo "X: ", x.value
    echo "Y: ", y.value
    check y.value == 4
```
