Skip to content

Instantly share code, notes, and snippets.

@lancewalton
Last active October 20, 2021 15:41
Show Gist options
  • Select an option

  • Save lancewalton/a56a91e16de9c03715e55bcc903ea120 to your computer and use it in GitHub Desktop.

Select an option

Save lancewalton/a56a91e16de9c03715e55bcc903ea120 to your computer and use it in GitHub Desktop.

Revisions

  1. lancewalton revised this gist Oct 20, 2021. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -18,12 +18,11 @@ class SignalTransformer extends FunSuite {
    val bars = Var[Option[Bar]](None)
    var shouldDequeue = true

    def dequeueNext(): Unit = {
    def dequeueNext(): Unit =
    if (shouldDequeue && queue.nonEmpty) {
    shouldDequeue = false
    fooToProcess.writer.onNext(queue.dequeue())
    }
    }

    def doFirst(foo: Foo): Unit = {
    Interpreter
    @@ -58,7 +57,7 @@ class SignalTransformer extends FunSuite {
    dequeueNext()
    }(owner)

    bars.signal.changes.collect { case Some(bar) => bar }
    EventStream.merge(EventStream.fromValue(bars.now()), bars.signal.changes).collect { case Some(bar) => bar }
    }

    test("StrictSignal") {
    @@ -73,4 +72,4 @@ class SignalTransformer extends FunSuite {
    $foo.set(foo2)
    $foo.set(foo3)
    }
    }
    }
  2. lancewalton revised this gist Oct 20, 2021. 1 changed file with 51 additions and 41 deletions.
    92 changes: 51 additions & 41 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,3 @@
    import com.raquo.laminar.api.L
    import com.raquo.laminar.api.L.*
    import munit.FunSuite

    @@ -7,60 +6,71 @@ import scala.collection.mutable
    case class Foo(s: String)
    case class Bar(s: String)

    object Collector {
    def apply[A](stream: EventStream[A], operations: () => Unit*): List[A] = {
    val result: mutable.ListBuffer[A] = mutable.ListBuffer.empty

    stream.foreach { a =>
    result.prepend(a)
    }(unsafeWindowOwner)

    operations.foreach(_())

    result.toList
    }
    }

    object Interpreter {
    def interpret(foo: Foo): EventStream[Bar] = EventStream.fromValue(Bar(foo.s))
    def interpretAndReconcile(foo: Foo, bar: Bar): EventStream[Bar] = EventStream.fromValue(Bar(s"${foo.s}(${bar.s})"))
    }

    class SignalTransformer extends FunSuite {
    def transform(foos: StrictSignal[Foo]): EventStream[Bar] =
    foos
    .foldLeft(Interpreter.interpret(_)) { case (accumulator: L.EventStream[Bar], foo: Foo) =>
    println(foo) // Just making sure things are getting called as I expect
    // The order of the parameters in this merge seems not to matter.
    EventStream.merge(accumulator.flatMap(Interpreter.interpretAndReconcile(foo, _)), accumulator)
    def transform(foos: StrictSignal[Foo], owner: Owner): EventStream[Bar] = {
    val queue = mutable.Queue.empty[Foo]
    val fooToProcess = new EventBus[Foo]
    val bars = Var[Option[Bar]](None)
    var shouldDequeue = true

    def dequeueNext(): Unit = {
    if (shouldDequeue && queue.nonEmpty) {
    shouldDequeue = false
    fooToProcess.writer.onNext(queue.dequeue())
    }
    .changes
    .flatten
    }

    test("StrictSignal") {
    def doFirst(foo: Foo): Unit = {
    Interpreter
    .interpret(foo)
    .foreach { bar =>
    bars.writer.onNext(Some(bar))
    shouldDequeue = true
    dequeueNext()
    }(owner)
    ()
    }

    def doSubsequent(acc: Bar, foo: Foo) = {
    Interpreter
    .interpretAndReconcile(foo, acc)
    .foreach { bar =>
    bars.writer.onNext(Some(bar))
    shouldDequeue = true
    dequeueNext()
    }(owner)
    ()
    }

    fooToProcess.events.foreach { foo =>
    bars
    .now()
    .fold(doFirst(foo))(currentBar => doSubsequent(currentBar, foo))
    }(owner)

    foos.foreach { foo =>
    queue.enqueue(foo)
    dequeueNext()
    }(owner)

    bars.signal.changes.collect { case Some(bar) => bar }
    }

    test("StrictSignal") {
    val foo1: Foo = Foo("1")
    val foo2: Foo = Foo("2")
    val foo3: Foo = Foo("3")

    val foos: Var[Foo] = Var(foo1)

    // I don't usually write tests with println. I'm just using munit to run this.
    println(
    Collector(
    transform(foos.signal),
    () => foos.set(foo2),
    () => foos.set(foo3)
    )
    )
    val $foo: Var[Foo] = Var(foo1)

    // What I get is:
    // Foo(2) -- this is from the println in the foldLeft
    // Foo(3) -- this is from the println in the foldLeft
    //
    // List(Bar(1), Bar(2(1))) -- this is from the collected output
    transform($foo.signal, unsafeWindowOwner).foreach(bar => println(bar))(unsafeWindowOwner)

    // What I want is (ignoring the two 'Foo' output lines):
    // List(Bar(1), Bar(2(1)), Bar(3(2(1))))
    $foo.set(foo2)
    $foo.set(foo3)
    }
    }
  3. lancewalton created this gist Oct 19, 2021.
    66 changes: 66 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,66 @@
    import com.raquo.laminar.api.L
    import com.raquo.laminar.api.L.*
    import munit.FunSuite

    import scala.collection.mutable

    case class Foo(s: String)
    case class Bar(s: String)

    object Collector {
    def apply[A](stream: EventStream[A], operations: () => Unit*): List[A] = {
    val result: mutable.ListBuffer[A] = mutable.ListBuffer.empty

    stream.foreach { a =>
    result.prepend(a)
    }(unsafeWindowOwner)

    operations.foreach(_())

    result.toList
    }
    }

    object Interpreter {
    def interpret(foo: Foo): EventStream[Bar] = EventStream.fromValue(Bar(foo.s))
    def interpretAndReconcile(foo: Foo, bar: Bar): EventStream[Bar] = EventStream.fromValue(Bar(s"${foo.s}(${bar.s})"))
    }

    class SignalTransformer extends FunSuite {
    def transform(foos: StrictSignal[Foo]): EventStream[Bar] =
    foos
    .foldLeft(Interpreter.interpret(_)) { case (accumulator: L.EventStream[Bar], foo: Foo) =>
    println(foo) // Just making sure things are getting called as I expect
    // The order of the parameters in this merge seems not to matter.
    EventStream.merge(accumulator.flatMap(Interpreter.interpretAndReconcile(foo, _)), accumulator)
    }
    .changes
    .flatten

    test("StrictSignal") {

    val foo1: Foo = Foo("1")
    val foo2: Foo = Foo("2")
    val foo3: Foo = Foo("3")

    val foos: Var[Foo] = Var(foo1)

    // I don't usually write tests with println. I'm just using munit to run this.
    println(
    Collector(
    transform(foos.signal),
    () => foos.set(foo2),
    () => foos.set(foo3)
    )
    )

    // What I get is:
    // Foo(2) -- this is from the println in the foldLeft
    // Foo(3) -- this is from the println in the foldLeft
    //
    // List(Bar(1), Bar(2(1))) -- this is from the collected output

    // What I want is (ignoring the two 'Foo' output lines):
    // List(Bar(1), Bar(2(1)), Bar(3(2(1))))
    }
    }