Created
June 14, 2017 12:05
-
-
Save biboudis/22ab1d4768725070eb42598f01e4388a to your computer and use it in GitHub Desktop.
Martin's complete, FRP example from coursera.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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