Всё очень просто:
HWCChain.scala:
//S: 1 import, for the tailcall annotation later.
import annotation._
/**
HWCChain is a Chain of HelloWordCharacters, but as a lean, concise language,
we do some abbrev. here.
We need hasNext () and next (), which is the iterator Pattern.
S: 1 type
S: 2 functions definitions
S: 4 function calls
S: 1 if
*/
trait HWCChain[T] extends Iterator [HWCChain[T]] with ContentProvider[T] {
// tailrec is just an instruction for the compiler, to warn us, if this code
// can't be tail call optimized.
@tailrec
final def go () : Unit = {
// ce is our ContentProvider.ce
System.out.print (ce);
// and here is our iterator at work, hasNext and next:
if (hasNext ()) next ().go ()
}
// per default, we have a next element (except our TermHWWChain, see close to bottom)
// this follows the DRY-principle, and reduces the code drastically.
override def hasNext (): Boolean = true
}
HHWCChain.scala:
/**
This is a 'H'-element, followed by the 'e'-Element.
S: 1 type
S: 2 functions
*/
case object HHWCChain extends HWCChain[Char] with ContentProvider[Char] {
override def ce = 'H'
override def next = eHWCChain
}
eHWCChain.scala:
/*
and here is the 'e'-Element, followed by l-Element 1, which is a new Type
S: 1 type
S: 2 functions
*/
case object eHWCChain extends HWCChain[Char] {
override def ce = 'e'
override def next = new indexedLHWCChain (1)
}
theLThing.scala:
/**
we have to distinguish the first, second and third 'l'-thing.
But of course, since all of them provide a l-character,
we extract the l for convenient reuse. That saves a lotta code, boy!
S: 1 type
S: 1 function
*/
trait theLThing extends HWCChain[Char] {
override def ce = 'l'
}
indexedLHWCChain.scala:
/**
depending on the l-number, we either have another l as next, or an o, or the d.
S: 1 type
S: 1 function definition
S: 2 function calls
S: 1 control structure (match/case)
*/
case class indexedLHWCChain (i: Int) extends theLThing {
override def next = i match {
case 1 => new indexedLHWCChain (2)
case 2 => new indexedOHWCChain (1)
case _ => dHWCChain
}
}
theOThing.scala:
// see theLTHing ...
//S: 1 type
//S: 1 function
trait theOThing extends HWCChain[Char] {
override def ce = 'o'
}
indexedOHWCChain.scala:
// and indexedOHWCCHain ...
//S: 1 type
//S: 1 function definition
//S: 1 function call
//S: 1 control structure
case class indexedOHWCChain (i: Int) extends theOThing {
override def next = i match {
case 1 => BlankHWCChain
case _ => rHWCChain
}
}
BlankHWCChain.scala:
// and indexedOHWCCHain ...
//S: 1 type
//S: 2 function definitions
case object BlankHWCChain extends HWCChain[Char] {
override def ce = ' '
override def next = WHWCChain
}
WHWCChain.scala:
//S: 1 type
//S: 2 function definitions
case object WHWCChain extends HWCChain[Char] {
override def ce = 'W'
override def next = new indexedOHWCChain (2)
}
rHWCChain.scala:
//S: 1 type
//S: 2 function definitions
case object rHWCChain extends HWCChain[Char] {
override def ce = 'r'
override def next = new indexedLHWCChain (3)
}
dHWCChain.scala:
//S: 1 type
//S: 2 function definitions
case object dHWCChain extends HWCChain[Char] {
override def ce = 'd'
override def next = TermHWCChain
}
TermHWCChain.scala:
/*
Here is the only case, where hasNext returns false.
For scientists: If you're interested in terminating programs, this type is
for you!
S: 1 type
S: 3 function definitions
*/
case object TermHWCChain extends HWCChain[Char] {
override def ce = '\n'
override def hasNext (): Boolean = false
override def next = TermHWCChain // dummy - has next is always false
}
HelloWorldCharChainChecker.scala: