# Actors

**URL:** <https://es.discourse.group/t/actors/801>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [May 30, 2021, 5:51am UTC](https://es.discourse.group/t/actors/801 "2021-05-30T05:51:08Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [May 30, 2021, 5:51am UTC](https://es.discourse.group/t/actors/801/1 "2021-05-30T05:51:08Z")

</div>

[Proposal link](https://github.com/isiahmeadows/proposal-es-actors)

It looks a lot like React hooks, and that's intentional as it's a partial inspiration, but I've extended that somewhat and gave it additional semantics with the goal to make it much more broadly useful, fulfilling many of the same functions as Backbone and Redux by making it a generic serializable state store rather than hard-coded to any particular pattern. (You can see this in action with my counters.)

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [June 2, 2021, 6:05pm UTC](https://es.discourse.group/t/actors/801/2 "2021-06-02T18:05:55Z")

</div>

This seems like a very interesting idea, and it's well thought out - I'm intrigued by its potential.

You've discussed a bit about how this concept might be used on a server, and the example you gave was basically moving UI state management logic to a server (but the results are still serialized and sent to a UI). Are there use cases for this idea that doesn't involve the UI at all?

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [June 3, 2021, 1:51am UTC](https://es.discourse.group/t/actors/801/3 "2021-06-03T01:51:28Z")

</div>

Copied from the proposal (emphasis added):

> - It glides right in perfectly with [tc39/proposal-eventual-send](https://github.com/tc39/proposal-eventual-send), providing a very nice and easy backend while letting those act as a front end. It might be worth adding a built-in wrapper for these as a follow-on if that takes off, or maybe even having async actor instances implement `[[EventualSend]]` and so on. **One could also imagine using it as the basis of something similar to Cloudflare's durable objects.**

This is in reference to [Cloudflare Durable Objects · Cloudflare Durable Objects docs](https://developers.cloudflare.com/workers/learning/using-durable-objects), if it helps. Conceptually, it has a _lot_ in common with Erlang's processes, just it's a more static form of it where Erlang's process dictionary is a very dynamic and free-form thing. [You could also compare it to Akka's actors, where it shares a lot more in common.](https://doc.akka.io/docs/akka/current/typed/actors.html) I focused on the UI side as it practically doesn't exist there, while in highly distributed and networked applications it's very popular.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 24, 2021, 12:34am UTC](https://es.discourse.group/t/actors/801/4 "2021-09-24T00:34:16Z")

</div>

The proposal says

> lessons from what worked well (React Hooks' state mechanism, virtual DOM,

But did those things go well? Solid.js is faster, easier to understand, without gotchas like stale closures (function components execute only once, not over and over), without virtual DOM.

A few reasons why Solid is great in a nutshell:

```jsx
import {createSignal, createEffect, render} from 'solid-js'

function MyApp() {
  // Reactive variable with initial value 0
  const [count, setCount] = createSignal(0)

  // Increment count every second
  setInterval(() => setCount(count() + 1), 1000)

  // Use count in the *DOM*
  const div = <div>count is {count()}</div>

  // This! This is true!!!!
  console.log(div instanceof HTMLDivElement) // true

  // Pass it to jQuery? Sure!
  jQuery(div).foo()

  // Log count every time it changes.
  createEffect(() => {
    console.log('count is', count())
  })

  console.log('This log only happens once!')

  return div
}

render(<MyApp />, document.body)

```

I need to study Actors though. I'm not learned in those yet. Brb.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 24, 2021, 12:48am UTC](https://es.discourse.group/t/actors/801/5 "2021-09-24T00:48:19Z")

</div>

Here's what that could look like with a language feature, minus the functional component and minus the JSX (left to the imagination):

```javascript
  // Reactive variable with initial value 0
  reactive count = 0

  // Increment count every second
  setInterval(() => count++, 1000)

  // Use count in the *DOM*
  const div = document.createElement('div')
  autorun {
    div.textContent = 'count is ' + count
  }

  // This! This is true!!!!
  console.log(div instanceof HTMLDivElement) // true

  // Pass it to jQuery? Sure!
  jQuery(div).foo()

  // Log count every time it changes.
  autorun {
    console.log('count is', count)
  }

  console.log('This log only happens once!')

  document.body.append(div)

```

Name bike shedding: `autorun` could be called `effect`, `reactive` could be `signal`, ...

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 24, 2021, 12:51am UTC](https://es.discourse.group/t/actors/801/6 "2021-09-24T00:51:03Z")

</div>

Here's a computed value, this time using the name `effect` in place of `autorun`:

```javascript
computed doubleCount = count * 2

// Log doubleCount any time it changes (use it anywhere you'd use a primitive reactive variable):
effect {
  console.log(doubleCount)
} 

```

`reactive` vars are writable as with `let`, `computed` vars are readonly like with `const` (although their values change if their dependencies are updated, just that the dev can't explicitly write to them).

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 24, 2021, 1:07am UTC](https://es.discourse.group/t/actors/801/7 "2021-09-24T01:07:29Z")

</div>

The language would handle nested effects (and this is the basis for all DOM component frameworks/libs):

```javascript
effect {
  // This effect reruns only when hasFoo changes.
  if (hasFoo) effect {
    // log foo when it changes, but the outer
    // effect will not rerun when foo changes
    console.log(foo)
  } else effect {
    // log bar when it changes, but the outer
    // effect will not rerun when bar changes
    console.log(bar)
  }
}

```

Where `hasFoo`, `foo`, and `bar` are `reactive` or `computed` variables.

The outer effect reruns only if `hasFoo` changes. Depending on which effect is reached during a rerun, no longer reached effects are stopped, and newly reached effects are started. When an inner effect is reached and started, the inner effect tracks it's dependencies and it can further reach inner-inner effects, and so on.

This is how all functional components essentially run (well, except for React, which tries to emulate this, but doesn't actually do this like Vue, Svelte, and Solid do). React's version should be disqualified from this because it causes confusion (hooks rules, stale closures from needlessly rerunning, etc).

Using these three primitives, we now have the ability to make functional components without a library:

Here's the original Solid example, but still without JSX (with `autorun` instead of `effect`, 🚲🏚 ):

```javascript
function ComponentA() {
  // Reactive variable with initial value 0
  reactive count = 0

  // Increment count every second
  setInterval(() => count++, 1000)

  // Use count in the *DOM*
  const div = document.createElement('div')
  autorun {
    div.textContent = 'count is ' + count
  }

  // This! This is true!!!!
  console.log(div instanceof HTMLDivElement) // true

  // Pass it to jQuery? Sure!
  jQuery(div).foo()

  // Log count every time it changes.
  autorun {
    console.log('count is', count)
  }

  console.log('This log only happens once!')
}

document.body.append(ComponentA())

```

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 24, 2021, 1:24am UTC](https://es.discourse.group/t/actors/801/8 "2021-09-24T01:24:23Z")

</div>

Now here's how nested effects allow component composition:

```javascript
function ComponentA {
  // Same as before
}

function ComponentB(props) {
  const wrapper = document.createElement('div')
  reactive blue = 0

  // Sprinkle of jQuery (if you're into that):
  $(wrapper).on('click', () => {
    blue = Math.round(255 * Math.random())
  })

  effect {
    wrapper.style.border = `${props.borderSize%5+1}px solid rgba(23, 45, ${blue})`
  }

  wrapper.append(ComponentA())

  return wrapper
}

function ComponentC(_props) {
  const props = {
    reactive borderSize: _props.initialBorderSize
  }

  setInterval(() => props.borderSize++, 2000)

  return ComponentB(props)
}

document.append(ComponentC({initialBorderSize: 3}))
// or with simple JSX sugar:
document.append(<ComponentC initialBorderSize={3} />)

```

As we can see, with these primitives we can do a lot, even have a UI component system (all that's needed is very simple JSX syntax to make it more terse, but without JSX no library or framework is even needed!).

We can extend arg structuring and parameter destructuring syntax to allow passing reactivity. Updated ComponentB and C:

```javascript
function ComponentB({computed borderSize}) {
  const wrapper = document.createElement('div')
  reactive blue = 0

  // Sprinkle of jQuery (if you're into that):
  $(wrapper).on('click', () => {
    blue = Math.round(255 * Math.random())
  })

  effect {
    wrapper.style.border = `${borderSize%5+1}px solid rgba(23, 45, ${blue})`
  }

  wrapper.append(ComponentA())

  return wrapper
}

function ComponentC({initialBorderSize/*(not reactive)*/}) {
  reactive borderSize = initialBorderSize

  setInterval(() => borderSize++, 2000)

  return ComponentB({send borderSize})
}

```

Finally the nested effects lend to component composition:

```javascript
function ComponentD() {
  reactive rand = Math.random()

  setInterval(() => rand = Math.random(), 2000)

  return rand >= 0.5
    ? ComponentB({borderSize: 3})
    : ComponentC({initialBorderSize: 4})
}

```

We can start to imagine how no-longer-reached and reached effects are started and stopped based on the ternary, and we can also imagine how it would be written with JSX sugar...

Furthermore, instead if starting and stopping effects in separate logic branches, one could spend one DOM or the other depending on which one should be visible (or toggle a class, etc). Components can handle this for you, and JSX would make it even more concise.

Everything above is essentially what Solid.js is, but with APIs and today's more limited JS syntax.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 24, 2021, 8:38am UTC](https://es.discourse.group/t/actors/801/9 "2021-09-24T08:38:44Z")

</div>

FWIW, I'm abandoning the proposal anyways - I'm no longer convinced it's a good idea.

**Edit:** Read up on [Actor model - Wikipedia](https://en.wikipedia.org/wiki/Actor_model) and cell-based reactive programming - those were my two largest inspirations. The syntax was inspired by React Hooks, but only _inspired_.

Also, the reason why I've revoked my proposal is that I've intuitively misinterpreted the core of the actor model. I've been coding a bit in Erlang lately, and of course I'm currently investigating how that changes things concurrency-wise because it handles concurrency drastically differently. And let's just say the way it inverts message processing is actually extremely useful.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 24, 2021, 8:44am UTC](https://es.discourse.group/t/actors/801/10 "2021-09-24T08:44:54Z")

</div>

This is even more React-like than my proposal. You basically just replicated React Hooks. Mine at least allowed custom handlers.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 25, 2021, 2:53pm UTC](https://es.discourse.group/t/actors/801/11 "2021-09-25T14:53:27Z")

</div>

It's not like React hooks though, it's Solid/Knockout/Mobx reactive computations. There's a fundamental difference. React hooks _imitates_ those, the runtime behavior is entirely different in React than the stuff in the above examples. React came _after_ these concepts and invented something _else_ to try to fit in, but it's a pretty bad fail at that (IMO).

There is a huge difference between how React works, and how the above works: in the above before the ComponentD example, ComponentA/B/C functions only ever execute _ **once** _. That's a huge difference, it is totally not like React, and this form of reactivity existed before React created that monster (Knockout.js, Meteor, Qt QML, etc), and Solid.js proves this concept can be one of the fastest while also providing an amazing developer experience. See Solid in these benchmarks:

[https://krausest.github.io/js-framework-benchmark/current.html](https://krausest.github.io/js-framework-benchmark/current.html)

The above dependency-tracking reactivity idea is perfected by Solid.js, but Solid didn't invent it, Solid created a simple ergonomic API with JSX DOM sugar for propagating reactive variables to DOM objects.

TLDR, a proposal for what Solid.js effectively does (and what Knockout, Meteor, Mobx, Qt QML, etc do, check those out) would be nice.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 26, 2021, 8:13am UTC](https://es.discourse.group/t/actors/801/12 "2021-09-26T08:13:46Z")

</div>

Yeah, I misread your proposal - I didn't look closely enough. (And I'm familiar with MobX - one of my workplace's open source projects uses it extensively.)

I do have a question: how would it conceptually work within the framework of a virtual DOM system (like Vue) or similar (like Svelte)?

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [September 28, 2021, 3:42pm UTC](https://es.discourse.group/t/actors/801/13 "2021-09-28T15:42:12Z")

</div>

Vdom wouldn't work within this concept, rather a vdom framework could just use or wrap these primitives, f.e. it would create effects and the effects would trigger vdom diffing, etc.

In the above example where I update `textContent` inside the effect, some library could similarly compile their JSX to modify a vdom tree instead of an actual-DOM tree based on changes of reactive variables, and the vdom framework could queue an update (queue a diff) from inside the effect.

It is no different than if the vdom library relied on an event emitter pattern, or something like setState like in React, or some value streaming API, to then queue updates. The depdency-tracking auto-running reactivity pattern is merely another way to observe changes, but once the changes are observed, any library can do whatever they want with the changes including update a vdom tree.

Vue works that way (reactive effects that trigger updates to a vdom tree).

Solid on the other hand uses reactive effects to update DOM directly instead of a vdom, but the auto-running dependency-tracking effects are in common with Vue, Svelte, and others.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [September 30, 2021, 4:47am UTC](https://es.discourse.group/t/actors/801/14 "2021-09-30T04:47:10Z")

</div>

You indirectly answered my question, but just to be clear, I was saying mostly the other way around, within the structure of a virtual DOM framework, not within the structure of your proposed construct.

---

<div class="post-metadata">

**Author:** ![trusktr](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/trusktr/32/183_2.png) [@trusktr](https://es.discourse.group/u/trusktr)\
**Post date:** [November 17, 2021, 5:32pm UTC](https://es.discourse.group/t/actors/801/15 "2021-11-17T17:32:49Z")

</div>

Yes, VDOM framework can use this dep-tracking reactivity paradigm in its implementation.

It would be very similar to, for example, using `MobX` inside of `React`, but I wouldn't consider it ideal because we're mixing more concepts that we need. MobX, when used inside React, is essentially the example of what you're saying: a vdom system that can re-render itself based on reactive signals.

What dep-tracking reactivity is good for is fine-grained updates, and mapping value changes directly to places that need the updated values whenever the values change.
