Scala: What is the difference between Traversable and Iterable traits in Scala collections?

后端 未结 4 1206
迷失自我
迷失自我 2020-12-04 09:05

I have looked at this question but still don\'t understand the difference between Iterable and Traversable traits. Can someone explain ?

4条回答
  •  情歌与酒
    2020-12-04 09:36

    tl;dr Iterables are Traversables that can produce stateful Iterators


    First, know that Iterable is subtrait of Traversable.

    Second,

    • Traversable requires implementing the foreach method, which is used by everything else.

    • Iterable requires implementing the iterator method, which is used by everything else.

    For example, the implemetation of find for Traversable uses foreach (via a for comprehension) and throws a BreakControl exception to halt iteration once a satisfactory element has been 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
      }
    }
    

    In contrast, the Iterable subtract overrides this implementation and calls find on the Iterator, which simply stops iterating once the element is found:

    trait Iterable {
      override /*TraversableLike*/ 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'd be nice not to throw exceptions for Traversable iteration, but that's the only way to partially iterate when using just foreach.

    From one perspective, Iterable is the more demanding/powerful trait, as you can easily implement foreach using iterator, but you can't really implement iterator using foreach.


    In summary, Iterable provides a way to pause, resume, or stop iteration via a stateful Iterator. With Traversable, it's all or nothing (sans exceptions for flow control).

    Most of the time it doesn't matter, and you'll want the more general interface. But if you ever need more customized control over iteration, you'll need an Iterator, which you can retrieve from an Iterable.

提交回复
热议问题