trait IsIterable[Repr] extends IsIterableOnce[Repr]
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 String
s (String
s
do not extend Iterable
, but can be converted to Iterable
)
IsIterable
provides three members:
- type member
A
, which represents the element type of the targetIterable[A]
- type member
C
, which represents the type returned by transformation operations that preserve the collection’s elements type - method
apply
, which provides a way to convert between the type we wish to add extension methods to,Repr
, andIterableOps[A, Iterable, C]
.
Usage
One must provide IsIterable
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, IterableOps} import scala.collection.generic.IsIterable class ExtensionMethods[Repr, I <: IsIterable[Repr]](coll: Repr, it: I) { def mapReduce[B](mapper: it.A => B)(reducer: (B, B) => B): B = { val iter = it(coll).iterator var res = mapper(iter.next()) while (iter.hasNext) res = reducer(res, mapper(iter.next())) res } } implicit def withExtensions[Repr](coll: Repr)(implicit it: IsIterable[Repr]): ExtensionMethods[Repr, it.type] = new ExtensionMethods(coll, it) // 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 Repr
, where
Repr
represents (typically) the collection type, and an argument it
of a subtype of IsIterable[Repr]
.
The body of the method starts by converting the coll
argument to an IterableOps
in order to
call the iterator
method on it.
The remaining of the implementation is straightforward.
The withExtensions
implicit conversion makes the mapReduce
operation available
on any type Repr
for which it exists an implicit IsIterable[Repr]
instance.
Note how we keep track of the precise type of the implicit it
argument by using the
it.type
singleton type, rather than the wider IsIterable[Repr]
type. We do that
so that the information carried by the type members A
and C
of the it
argument
is not lost.
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 IsIterable[Repr]
can be found. Given that the
IsIterable
companion object contains implicit members that return values of type
IsIterable
, this requirement is typically satisfied, and the chain
of interactions described in the previous paragraph is set into action.
(See the IsIterable
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 IsIterable
for New Types
One must simply provide an implicit value of type IsIterable
specific to the new type, or an implicit conversion which returns an
instance of IsIterable
specific to the new type.
Below is an example of an implementation of the IsIterable
trait
where the Repr
type is Range
.
implicit val rangeRepr: IsIterable[Range] { type A = Int; type C = IndexedSeq[Int] } = new IsIterable[Range] { type A = Int type C = IndexedSeq[Int] def apply(coll: Range): IterableOps[Int, IndexedSeq, IndexedSeq[Int]] = coll }
(Note that in practice the IsIterable[Range]
instance is already provided by
the standard library, and it is defined as an IsSeq[Range]
instance)
- Source
- IsIterable.scala
- Alphabetic
- By Inheritance
- IsIterable
- IsIterableOnce
- AnyRef
- Any
- by any2stringadd
- by StringFormat
- by Ensuring
- by ArrowAssoc
- Hide All
- Show All
- Public
- Protected
Type Members
- abstract type A
The type of elements we can traverse over (e.g.
The type of elements we can traverse over (e.g.
Int
).- Definition Classes
- IsIterableOnce
- abstract type C
The type returned by transformation operations that preserve the same elements type (e.g.
The type returned by transformation operations that preserve the same elements type (e.g.
filter
,take
).In practice, this type is often
Repr
itself, excepted in the case ofSeqView[A]
(and otherView[A]
subclasses), where it is “only”View[A]
.
Abstract Value Members
- abstract def apply(coll: Repr): IterableOps[A, Iterable, C]
A conversion from the type
Repr
toIterableOps[A, Iterable, C]
A conversion from the type
Repr
toIterableOps[A, Iterable, C]
- Definition Classes
- IsIterable → IsIterableOnce
Deprecated Value Members
- val conversion: (Repr) => IterableOps[A, Iterable, C]
- Definition Classes
- IsIterable → IsIterableOnce
- Annotations
- @deprecated
- Deprecated
(Since version 2.13.0) 'conversion' is now a method named 'apply'
This is the documentation for the Scala standard library.
Package structure
The scala package contains core types like
Int
,Float
,Array
orOption
which are accessible in all Scala compilation units without explicit qualification or imports.Notable packages include:
scala.collection
and its sub-packages contain Scala's collections frameworkscala.collection.immutable
- Immutable, sequential data-structures such asVector
,List
,Range
,HashMap
orHashSet
scala.collection.mutable
- Mutable, sequential data-structures such asArrayBuffer
,StringBuilder
,HashMap
orHashSet
scala.collection.concurrent
- Mutable, concurrent data-structures such asTrieMap
scala.concurrent
- Primitives for concurrent programming such asFutures
andPromises
scala.io
- Input and output operationsscala.math
- Basic math functions and additional numeric types likeBigInt
andBigDecimal
scala.sys
- Interaction with other processes and the operating systemscala.util.matching
- Regular expressionsOther packages exist. See the complete list on the right.
Additional parts of the standard library are shipped as separate libraries. These include:
scala.reflect
- Scala's reflection API (scala-reflect.jar)scala.xml
- XML parsing, manipulation, and serialization (scala-xml.jar)scala.collection.parallel
- Parallel collections (scala-parallel-collections.jar)scala.util.parsing
- Parser combinators (scala-parser-combinators.jar)scala.swing
- A convenient wrapper around Java's GUI framework called Swing (scala-swing.jar)Automatic imports
Identifiers in the scala package and the
scala.Predef
object are always in scope by default.Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example,
List
is an alias forscala.collection.immutable.List
.Other aliases refer to classes provided by the underlying platform. For example, on the JVM,
String
is an alias forjava.lang.String
.