Scala 2.12 (and earlier version) feature TraversableOnce. Since both Iterator and Iterable implement TraversableOnce, it can be used to avoid object allocations: For example, consider the function
def foo(bar: TraversableOnce[Bar]) = if (bar.isEmpty) 0 else 1
This function can be applied to either an iterator or some container and, in either case, there will no object allocation in practice, which I always considered an outstanding feature of the Scala collections.
In Scala 2.13, TraversableOnce is deprecated and synonymous to IterableOnce. When I compile foo with the 2.13.0 compiler, I obtain the following warning:
Warning: method isEmpty in class IterableOnceExtensionMethods is deprecated (since 2.13.0): Use .iterator.isEmpty instead
So this warning suggests to change the 2.13 version of foo to:
def foo(bar: IterableOnce[Bar]) = if (bar.iterator.isEmpty) 0 else 1
Now, when bar is an iterator, there will be an additional call to iterator but no additional object allocation. (Let’s hope some optimizer gets rid of this call sooner or later.) However, when bar is some container, then an iterator object will be created. Considering the fact that typical container implementations provide an efficient isEmpty implementation, the iterator creation is an unnecessary and huge overhead.
I am the author of the optimization tool Yuck and performance is key. In its guts, the tool relies heavily on TraversableOnce and the flexibility it provides. Hence I am very concerned about this deprecation.
Looking at the documentation of IterableOnce, the goal of this deprecation seems to be:
The goal is to provide a minimal interface without any sequential operations. This allows
third-party extension like Scala parallel collections to integrate at the level of IterableOnce
without inheriting unwanted implementations.
What’s the problem with the default implementations? I mean, when you have a better implementation, you just override in your subclass.