Search code examples
scalafunctional-programmingreactive-programming

Two implementation for signal in scala - one fires an event on text change and other doesnot


I have to implement a function which takes signal of remaining char count to compute the signal of color i.e.

  • If there are 15 or more characters left, the color "green"
  • If there are between 0 and 14 characters left, included, the color "orange"
  • Otherwise (if the remaining count is negative), the color "red"

I have implemented this in following way:

remainingCharsCount() match {
  case x if x < 0 => Signal("red")
  case x if x >= 14 =>  Signal("green")
  case _ =>  Signal("orange")
}

where remainingCharsCount: Signal[Int] is a signal of remaining characters in a text.

The problem with the implementation above is that it does not fire events for color change based on remaining text count. In other implementations, I have moved the logic for color change inside the Signal block.

This code works fine:

Signal {
  val rc = remainingCharsCount()
  if (rc >= 15) "green"
  else if (rc >= 0) "orange"
  else "red"
}

Can someone explain what I am doing wrong in the first implementation?

For more info you can refer this link: https://github.com/ujjkumsi/FPDesign/blob/master/README.md


Solution

  • In the first approach, remainingCharsCount() is called once using which the pattern matching result is evaluated.

    In the second approach, everything happens inside a Signal block. In Signal { block }, block is the code which gets evaluated when dependencies change. The dependencies are created by the signals been used inside the callers.

    For example: remainingCharsCount() adds the caller, the returned Signal in your case to it's observers.

    See the apply() method in: https://github.com/omirho/scalafun2/blob/master/calculator/src/main/scala/calculator/Signal.scala

    Also see the other method implementations.

    Let me explain this a little more. In approach 1:

    remainingCharsCount() gets evaluated and gets assigned to a value. And the outer signal (which can't be seen in this code and can be treated as nil) gets added to its observers. The value is then used for pattern matching to construct a constant Signal. Hence, the required dependency is not created.

    Approach 2 has been explained before.