So far I have this Sequence
class:
case class Sequence[A](initialElems: A*) {
private val elems = scala.collection.mutable.ArrayBuffer[A]()
// initialize
elems ++= initialElems
}
With that code I can create new Sequence
instances like this:
val strings = Sequence("a", "b", "c")
val nums = Sequence(1, 2, 3, 4, 5)
Next, I’ll modify Sequence
so I can use it as a generator in a for
loop.
Note: I intentionally use the word “loop” in this lesson because all I’m trying to do is to loop over the elements in the
Sequence
, like a Javafor
loop. I’m specifically not trying to write for/yield expressions.
Trying to use Sequence in a simple `for` loop
To get started, let’s see what happens if I try to use a Sequence
in a simple for
loop. When I paste these two lines of code into the Scala REPL:
val ints = Sequence(1, 2, 3)
for (i <- ints) println(i)
I see this error after the for
loop:
scala> for (i <- ints) println(i)
<console>:14: error: value foreach is not a member of Sequence[Int]
for (i <- ints) println(i)
^
The bad news is that Sequence
won’t work in a simple for
loop. But the good news is that the Scala compiler error tells me what’s wrong:
"value foreach is not a member of Sequence[Int]"
How to modify Sequence so it can be used as a `for` loop generator
The error message tells me that this for
loop won’t work because Sequence
doesn’t have a foreach
method, so I’ll go ahead and implement one.
Because (a) Sequence
uses an ArrayBuffer
behind the scenes, and (b) I’m not concerned with how I implement the foreach
method, I’ll just piggyback on the ArrayBuffer
’s foreach
method:
def foreach(block: A => Unit): Unit = {
elems.foreach(block)
}
(As I mentioned in the last lesson, for the purposes of understanding how the for
expression works I don’t care how I implement a foreach
method, I just want to create one as simply as possible to see if that lets me use Sequence
inside of for
.)
Adding foreach
makes my complete Sequence
class look like this:
case class Sequence[A](initialElems: A*) {
private val elems = scala.collection.mutable.ArrayBuffer[A]()
// initialize
elems ++= initialElems
def foreach(block: A => Unit): Unit = {
elems.foreach(block)
}
}
When I paste that class into the REPL, and then paste this code in as well:
val ints = Sequence(1,2,3)
for (i <- ints) println(i)
I see that Sequence
now works as a for
loop generator:
scala> for (i <- ints) println(i)
1
2
3
Excellent. Let’s move on to the next step.
Exercises
- If you don’t like the way I implemented
foreach
, go ahead and implement it however you’d like. I recommend using recursion!