tindzk / MetaRx

Reactive data structures for Scala and Scala.js
35 stars 13 forks source link

Separate state from data propagation specification #22

Open tindzk opened 9 years ago

tindzk commented 9 years ago

Var, Opt etc. store the current values internally. This prevents their usage in reusable components. The goal would be to make channels immutable with regards to their state. However, the specified pipeline will still be mutable as it usually doesn't change once set up.

Given a web server with multiple users:

object MyLink {
  val url = Var("http://google.com/")
  val a = tag.a()
  a.href.subscribe(url)
}

import metarx.state  // Takes a number of channels to compose a new state object

def onRequest(url: String): String = {
  implicit val s = state(url)
  MyLink.url := url
  val myA = MyLink.a.instantiate(s)
  myA.toHtml
}

The example is contrived, but it shows how the specified data propagation pipeline could be reused across several requests. There are some challenges involved, for example how the state gets passed around.

A tentative sketch would look like this:

trait State {
  def set(ch: Var[_], value: Any)
  def query(ch: Var[_]): Any
  def attach(ch: Var[_], f: Nothing => Unit)
}

sealed class Var[T](init: T) {
  val subscribers = ArrayBuffer.empty[ImmutableVar[_]]
  def get(implicit s: State): T = s.query(this).asInstanceOf[T]
  def :=(value: T)(implicit s: State) = s.set(this, value)
  def map(f: T => T): Var[T] = ???
  def attach(f: T => Unit)(implicit s: State) {
    s.attach(this, f)
  }
}
darkfrog26 commented 9 years ago
sealed class Var[T](init: => T)

Seems like a better way to handle this since the initial value could be something that could change with each "instance".

darkfrog26 commented 9 years ago

what if instead of some strange concept of state you instead deal with these a little differently:

sealed class Var[T](init: => T) {
  ...
  def instantiate: VarInstance[T] = new VarInstance[T](this)
}

class VarInstance[T](var: Var[T]) {
  ... setup based on content of Var ...
}