Stream of numbers

In the previous blog we created a NumberDispenser class that dispenses numbers to its clients. It has a counter that keeps track of the next number to dispense. In this blog we will explore an alternate mechanism for handing out these numbers. The idea of this blog is to learn the Scala language and although the precious version of the NumberDispenser serves the purpose, let us investigate if there is any other way to get this functionality implemented in Scala.

Remember the goal of NumberDispenser is to keep handing out the next available number. In a way, it needs to have a steady stream of numbers to hand out.  Scala provides a data structure from its collections library that fits in here perfectly. The data structure is called Stream and it’s a List except that it’s a lazy list which means that all the elements of Stream are not evaluated right away. They are evaluated only when they are needed. This fits our need perfectly since we need to evaluate the next number to hand out only when someone requests that number. Let’s see how this is implemented –

[sourcecode language=”scala”]
class NumberDispenser(startingNumber: Int) {
private def numberStream(num: Int): Stream[Int] =
num #:: numberStream(num + 1)

private var nextNumberStream = numberStream(startingNumber)

// Methods of this class
def dispense: Int = {
val nextNum = nextNumberStream.head
nextNumberStream = nextNumberStream.tail
nextNum
}

def reset (resetTo: Int) {nextNumberStream = numberStream(resetTo)}
def peek = nextNumberStream.head
}
[/sourcecode]

We got rid of the counter from the previous version and replaced it with a number stream instead. This number stream is served by the method numberStream which returns a Stream where only the head of the stream is evaluated, the tail of the stream is not evaluated right away. If we examine the numberStream method it states that our stream is a sequence of numbers starting at num and the rest of the sequence is the stream that starts at num + 1. Such a sequence is created using the #:: operator which works by not evaluating the right hand side of the expression until it is requested. The right hand side is only requested when someone calls the dispense method at which point, the tail of the stream starting at num+1 needs to become the new stream. This cycle will continue as dispense method is called.

Testing

The same test cases from the previous blog will work for this class since we did not modify the behavior of the class we just changed the inner workings. That is the beauty of Scala, it provides the best of both worlds – Object Oriented as well as functional programming. However, lets take this opportunity to introduce “Behavior Driven Design” using Scala specs framework. Here is the source code for the test case. We will discuss the test case in a minute.

[sourcecode language=”scala”]
import org.specs._
import runner.ScalaTest
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
class NumberDispenserExperimentTest extends Specification with ScalaTest {
private val numberDispenser = new NumberDispenser(200)

"Number Dispenser" should {

"dispense numbers in a sequential order" in {
numberDispenser.dispense must_== 200
numberDispenser.dispense must_== 201
}

"allow us to reset it to any number. It should then dispense numbers from that number onwards" in {
numberDispenser.peek must_== 200
numberDispenser.reset(100)
numberDispenser.peek must_== 100
}

"let us peek at the next number without dispensing or advancing to the next number" in {
numberDispenser.peek must_== 200
numberDispenser.peek must_== 200
numberDispenser.peek must_== 200
}
}

}
[/sourcecode]

The specs framework allows us to define the specification for our system. You define the specification using a declarative syntax as shown in the above example.  We start by extending the Specification class to create our own specification for the system. Inside our specification class we write the specification as a string and use the keywords, “should”, “can” etc. For example, “Number  Dispenser” should {…}. What is happening in this case is that the string “Number Dispenser” is being converted automatically to a type that supports the  “should” method. The technique used in this case is called implicit conversion. If the Scala compiler comes across something that it cannot resolve on the default object type i.e. it gets a type error, it will look for a user defined implicit conversion from the default type to another type that could be used to resolve the error. In the case above, the specs framework defines an implicit conversion from String to a type that can handle the “should” method.

Once the specification is described for a system, you can define examples of the specification inside the body of should followed by the keyword “in”. Again, specs framework is providing implicit conversions from String type to a type that supports the “in” method. Once the examples have been listed, they can be backed with expectations and that is what is provided inside the curly braces following the “in” keyword. The “expectations” are what the specs framework will use to test if the functionality is correctly implemented by the system.

Executing the tests

Executing the test case is similar to how we executed the ScalaTest in the previous blog. We used the JUnitRunner that comes with ScalaTest framework and we use the RunWith annotation provided by JUnit 4. The only additional thing we need to do here is to mix in the ScalaTest trait along with the Specification trait.

Another way to execute a specs test if we mix in SpecificationWithJUnit trait. instead of just the Specification trait like this.

[sourcecode language=”scala”]
class NumberDispenserExperimentTest extends SpecificationWithJUnit {
[/sourcecode]

Conclusion

In today’s blog we discovered another way of serving numbers using a Scala Stream, a lazily evaluated list class that provides a capability of infinite numbers without computing all of them upfront. As the numbers are requested they are handed out.

In the next blog we will see how to make the NumberDispenser thread safe using Scala’s Actor model.

Leave a Reply

Your email address will not be published. Required fields are marked *