Packages

trait IsIterableLike[Repr] extends AnyRef

A trait which can be used to avoid code duplication when defining extension methods that should be applicable both to existing Scala collections (i.e., types extending Iterable) as well as other (potentially user-defined) types that could be converted to a Scala collection type. This trait makes it possible to treat Scala collections and types that can be implicitly converted to a collection type uniformly. For example, one can provide extension methods that work both on collection types and on Strings (Strings do not extend Iterable, but can be converted to Iterable)

IsIterable provides two members:

  1. type member A, which represents the element type of the target Iterable[A]
  2. value member conversion, which provides a way to convert between the type we wish to add extension methods to, Repr, and Iterable[A].
Usage

One must provide IsIterableLike as an implicit parameter type of an implicit conversion. Its usage is shown below. Our objective in the following example is to provide a generic extension method mapReduce to any type that extends or can be converted to Iterable. In our example, this includes String.

  import scala.collection.Iterable
  import scala.collection.generic.IsIterableLike

  class ExtensionMethods[A, Repr](coll: IterableLike[A, Repr]) {
    def mapReduce[B](mapper: A => B)(reducer: (B, B) => B): B = {
      val iter = coll.toIterator
      var res = mapper(iter.next())
      while (iter.hasNext)
        res = reducer(res, mapper(iter.next()))
      res
    }
  }

  implicit def withExtensions[Repr](coll: Repr)(implicit Iterable: IsIterableLike[Repr]) =
    new ExtensionMethods(Iterable.conversion(coll))

// See it in action!
List(1, 2, 3).mapReduce(_ * 2)(_ + _) // res0: Int = 12
"Yeah, well, you know, that's just, like, your opinion, man.".mapReduce(x => 1)(_ + _) // res1: Int = 59

Here, we begin by creating a class ExtensionMethods which contains our mapReduce extension method. Note that ExtensionMethods takes a constructor argument coll of type IterableLike[A, Repr], where A represents the element type and Repr represents (typically) the collection type. The implementation of mapReduce itself is straightforward.

The interesting bit is the implicit conversion withExtensions, which returns an instance of ExtensionMethods. This implicit conversion can only be applied if there is an implicit value Iterable of type IsIterableLike[Repr] in scope. Since IsIterableLike provides value member conversion, which gives us a way to convert between whatever type we wish to add an extension method to (in this case, Repr) and IterableLike[A, Repr], we can now convert coll from type Repr to IterableLike[A, Repr]. This allows us to create an instance of the ExtensionMethods class, which we pass our new IterableLike[A, Repr] to.

When the mapReduce method is called on some type of which it is not a member, implicit search is triggered. Because implicit conversion withExtensions is generic, it will be applied as long as an implicit value of type IsIterableLike[Repr] can be found. Given that IsIterableLike contains implicit members that return values of type IsIterableLike, this requirement is typically satisfied, and the chain of interactions described in the previous paragraph is set into action. (See the IsIterableLike companion object, which contains a precise specification of the available implicits.)

Note: Currently, it's not possible to combine the implicit conversion and the class with the extension methods into an implicit class due to limitations of type inference.

Implementing IsIterableLike for New Types

One must simply provide an implicit value of type IsIterableLike specific to the new type, or an implicit conversion which returns an instance of IsIterableLike specific to the new type.

Below is an example of an implementation of the IsIterableLike trait where the Repr type is String.

implicit val stringRepr: IsIterableLike[String] { type A = Char } =
  new IsIterableLike[String] {
    type A = Char
    val conversion = implicitly[String => IterableOps[Char, Any, String]]
  }
Linear Supertypes
AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. IsIterableLike
  2. AnyRef
  3. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Type Members

  1. abstract type A

    The type of elements we can traverse over.

Abstract Value Members

  1. abstract val conversion: (Repr) ⇒ IterableOps[A, Iterable, Repr]

    A conversion from the representation type Repr to IterableOps[A, Iterable, Repr].

Concrete Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  6. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  7. def equals(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  8. def finalize(): Unit
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  9. final def getClass(): Class[_]
    Definition Classes
    AnyRef → Any
  10. def hashCode(): Int
    Definition Classes
    AnyRef → Any
  11. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  12. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  13. final def notify(): Unit
    Definition Classes
    AnyRef
  14. final def notifyAll(): Unit
    Definition Classes
    AnyRef
  15. final def synchronized[T0](arg0: ⇒ T0): T0
    Definition Classes
    AnyRef
  16. def toString(): String
    Definition Classes
    AnyRef → Any
  17. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  18. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  19. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )

Inherited from AnyRef

Inherited from Any

Ungrouped