One of the sad facts of Scala is that recursive type aliases are not supported. Performing the following in REPL results in the following:
scala> type WalkFn = Function[Int, WalkFn] <console>:7: error: illegal cyclic reference involving type WalkFn type WalkFn = Function[Int, WalkFn] ^
Another remark is that Scala does not allow changing values by reference (as a rule, frowning, no, completely hates the functional programming paradigm).
However, do not be embarrassed! There are other options. Traits can be self-referential, and functions are just classes in Scala. In this way, we can model a common recursive WalkFn with traits. In addition, we can use immutable values, and our function returns the next progress, and does not mutate the parameter by reference.
Since the following contains circular references (WalkForward → WalkBackward, WalkBackward → WalkForward, etc.), you need to enter :paste in Scala REPL before starting the next example (so that the Scala Compiler will compile all 3 Walk{Forward,Backward,Equal} implementations in one step.
At first:
$ scala Welcome to Scala version 2.11.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05). Type in expressions to have them evaluated. Type :help for more information. scala> :paste // Entering paste mode (ctrl-D to finish)
Now paste the code:
import scala.util.Random object Helpers { def pickRandom[A](items: A*) = items(Random.nextInt(items.length)) } trait WalkFn extends (Int => (Int, WalkFn)) {} object WalkForward extends WalkFn { def apply(i: Int) = ( i + Random.nextInt(6), Helpers.pickRandom(WalkEqual, WalkBackward) ) } object WalkEqual extends WalkFn { def apply(i: Int) = ( i + (Random.nextInt(7) - 3), Helpers.pickRandom(WalkForward, WalkBackward) ) } object WalkBackward extends WalkFn { def apply(i: Int) = ( Random.nextInt(6) - 3, Helpers.pickRandom(WalkEqual, WalkForward) ) } def doWalk(count: Int, walkFn: WalkFn = WalkEqual, progress: Int = 0): Unit = if (count > 0) { val (nextProgress, nextStep) = walkFn(progress) println(nextProgress) doWalk(count - 1, nextStep, nextProgress) } doWalk(20)
Then, as instructed, press ctrl-D .
Enjoy a functional drunk step!