tl; dr Iterables are Traversables that stateful Iterators can create.
First, be aware that Iterable is a Traversable subtraction.
Secondly,
Traversable requires the use of the foreach method, which is used by everyone else.
Iterable requires the use of the iterator method, which is used by everyone else.
For example, to implement find for Traversable , foreach used (through a for understanding) and throws a BreakControl exception to stop the iteration after a satisfactory element is found.
trait TravserableLike { def find(p: A => Boolean): Option[A] = { var result: Option[A] = None breakable { for (x <- this) if (p(x)) { result = Some(x); break } } result } }
Unlike subtraction, Iterable overrides this implementation and calls find on iterator , which simply stops the iteration after finding the element:
trait Iterable { override def find(p: A => Boolean): Option[A] = iterator.find(p) } trait Iterator { def find(p: A => Boolean): Option[A] = { var res: Option[A] = None while (res.isEmpty && hasNext) { val e = next() if (p(e)) res = Some(e) } res } }
It would be nice to not throw exceptions for the Traversable iteration, but this is the only way to partially iterate using only foreach .
On the one hand, Iterable is a more demanding / powerful feature, since you can easily implement foreach with iterator , but you cannot implement iterator with foreach .
Thus, Iterable provides a way to pause, resume, or stop an iteration through a stateful iterator . With Traversable all of this or nothing (no exceptions for flow control).
In most cases, this does not matter, and you need a more general interface. But if you need more individual control over the iteration, you will need an iterator , which you can get from Iterable .
Paul Draper Oct 04 '15 at 22:32 2015-10-04 22:32
source share