You have an inherent problem. Iterable implies that you can get multiple iterators. Iterator implies that you can only go through once. This means that your Iterable[Iterable[T]] should be able to create Iterator[Iterable[T]] s. But when it returns an element - a Iterable[T] - and which requests several iterators, the basic single iterator cannot execute without caching the list results (too large) or invoking the original iteration and going through absolutely everything again (very inefficient).
So, although you can do this, I think you should understand your problem differently.
If you could start with Seq instead, you could capture the subsets as ranges.
If you already know how you want to use your iterative option, you can write a method
def process[T](source: Iterable[T])(starts: T => Boolean)(handlers: T => Unit *)
which each time increases the number of handlers when starts disables "true". If in any way you can do your processing in one pass, then it will be so. (However, your handlers will need to maintain state through mutable data structures or variables.)
If you can allow iterations in the external list to split the internal list, you can have Iterable[Iterator[T]] with the additional restriction that after repeated iteration to the later subterator, all previous subterators are invalid.
Here is the solution of the latter type (from Iterator[T] to Iterator[Iterator[T]] ; it can be wrapped to make the outer layers Iterable instead).
class GroupedBy[T](source: Iterator[T])(starts: T => Boolean) extends Iterator[Iterator[T]] { private val underlying = source private var saved: T = _ private var cached = false private var starting = false private def cacheNext() { saved = underlying.next starting = starts(saved) cached = true } private def oops() { throw new java.util.NoSuchElementException("empty iterator") }
source share