Skip to content

Instantly share code, notes, and snippets.

@biboudis
Created June 14, 2017 12:05
Show Gist options
  • Save biboudis/22ab1d4768725070eb42598f01e4388a to your computer and use it in GitHub Desktop.
Save biboudis/22ab1d4768725070eb42598f01e4388a to your computer and use it in GitHub Desktop.
Martin's complete, FRP example from coursera.
object FRP {
class Signal[T](expr: => T) {
import Signal._
private var myExpr: () => T = _
private var myValue: T = _
private var observers: Set[Signal[_]] = Set()
update(expr)
protected def update(expr: => T): Unit = {
myExpr = () => expr
computeValue()
}
protected def computeValue(): Unit = {
val newValue = caller.withValue(this)(myExpr())
if (myValue != newValue) {
myValue = newValue
val obs = observers
observers = Set()
obs.foreach(_.computeValue())
}
}
def apply() = {
observers += caller.value
assert(!caller.value.observers.contains(this), "cyclic signal definition")
myValue
}
}
object Signal {
val caller = new StackableVariable[Signal[_]](NoSignal)
def apply[T](expr: => T) = new Signal(expr)
}
class Var[T](expr: => T) extends Signal[T](expr) {
override def update(expr: => T): Unit = super.update(expr)
}
object Var {
def apply[T](expr: => T) = new Var(expr)
}
class StackableVariable[T](init: T) {
private var values: List[T] = List(init)
def value: T = values.head
def withValue[R](newValue: T)(op: => R): R = {
values = newValue :: values
try op
finally values = values.tail
}
}
object NoSignal extends Signal[Nothing](???) {
override def computeValue(): Unit = ()
}
def test() = {
var num = Signal(1)
val twice = Signal(num() * 2)
num() = 2
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment