diff --git a/base/generator.jl b/base/generator.jl index 75625c2c40525..e598f9318c29f 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -35,6 +35,23 @@ immutable HasLength <: IteratorSize end immutable HasShape <: IteratorSize end immutable IsInfinite <: IteratorSize end +""" + iteratorsize(itertype::Type) -> IteratorSize + +Given the type of an iterator, returns one of the following values: + +* `SizeUnknown()` if the length (number of elements) cannot be determined in advance. +* `HasLength()` if there is a fixed, finite length. +* `HasShape()` if there is a known length plus a notion of multidimensional shape (as for an array). + In this case the `size` function is valid for the iterator. +* `IsInfinite()` if the iterator yields values forever. + +The default value (for iterators that do not define this function) is `HasLength()`. +This means that most iterators are assumed to implement `length`. + +This trait is generally used to select between algorithms that pre-allocate space for their +result, and algorithms that resize their result incrementally. +""" iteratorsize(x) = iteratorsize(typeof(x)) iteratorsize(::Type) = HasLength() # HasLength is the default @@ -47,6 +64,20 @@ abstract IteratorEltype immutable EltypeUnknown <: IteratorEltype end immutable HasEltype <: IteratorEltype end +""" + iteratoreltype(itertype::Type) -> IteratorEltype + +Given the type of an iterator, returns one of the following values: + +* `EltypeUnknown()` if the type of elements yielded by the iterator is not known in advance. +* `HasEltype()` if the element type is known, and `eltype` would return a meaningful value. + +`HasEltype()` is the default, since iterators are assumed to implement `eltype`. + +This trait is generally used to select between algorithms that pre-allocate a specific +type of result, and algorithms that pick a result type based on the types of yielded +values. +""" iteratoreltype(x) = iteratoreltype(typeof(x)) iteratoreltype(::Type) = HasEltype() # HasEltype is the default diff --git a/doc/manual/interfaces.rst b/doc/manual/interfaces.rst index 15465047b2402..92af7faf5f5ea 100644 --- a/doc/manual/interfaces.rst +++ b/doc/manual/interfaces.rst @@ -11,16 +11,18 @@ A lot of the power and extensibility in Julia comes from a collection of informa Iteration --------- -================================= ======================== =========================================== -Required methods Brief description -================================= ======================== =========================================== -:func:`start(iter) ` Returns the initial iteration state -:func:`next(iter, state) ` Returns the current item and the next state -:func:`done(iter, state) ` Tests if there are any items remaining -**Important optional methods** **Default definition** **Brief description** -:func:`eltype(IterType) ` ``Any`` The type the items returned by :func:`next` -:func:`length(iter) ` (*undefined*) The number of items, if known -================================= ======================== =========================================== +================================================== ======================== =========================================== +Required methods Brief description +================================================== ======================== =========================================== +:func:`start(iter) ` Returns the initial iteration state +:func:`next(iter, state) ` Returns the current item and the next state +:func:`done(iter, state) ` Tests if there are any items remaining +**Important optional methods** **Default definition** **Brief description** +:func:`eltype(IterType) ` ``Any`` The type the items returned by :func:`next` +:func:`length(iter) ` (*undefined*) The number of items, if known +:func:`iteratorsize(IterType) ` ``HasLength()`` +:func:`iteratoreltype(IterType) ` ``HasEltype()`` +================================================== ======================== =========================================== Sequential iteration is implemented by the methods :func:`start`, :func:`done`, and :func:`next`. Instead of mutating objects as they are iterated over, Julia provides these three methods to keep track of the iteration state externally from the object. The :func:`start(iter) ` method returns the initial state for the iterable object ``iter``. That state gets passed along to :func:`done(iter, state) `, which tests if there are any elements remaining, and :func:`next(iter, state) `, which returns a tuple containing the current element and an updated ``state``. The ``state`` object can be anything, and is generally considered to be an implementation detail private to the iterable object. diff --git a/doc/stdlib/collections.rst b/doc/stdlib/collections.rst index 54482d0e4136c..0c1648cb4294b 100644 --- a/doc/stdlib/collections.rst +++ b/doc/stdlib/collections.rst @@ -108,6 +108,34 @@ type. An iterator that generates the value ``x`` forever. If ``n`` is specified, generates ``x`` that many times (equivalent to ``take(repeated(x), n)``\ ). +.. function:: iteratorsize(itertype::Type) -> IteratorSize + + .. Docstring generated from Julia source + + Given the type of an iterator, returns one of the following values: + + * ``SizeUnknown()`` if the length (number of elements) cannot be determined in advance. + * ``HasLength()`` if there is a fixed, finite length. + * ``HasShape()`` if there is a known length plus a notion of multidimensional shape (as for an array). In this case the ``size`` function is valid for the iterator. + * ``IsInfinite()`` if the iterator yields values forever. + + The default value (for iterators that do not define this function) is ``HasLength()``\ . This means that most iterators are assumed to implement ``length``\ . + + This trait is generally used to select between algorithms that pre-allocate space for their result, and algorithms that resize their result incrementally. + +.. function:: iteratoreltype(itertype::Type) -> IteratorEltype + + .. Docstring generated from Julia source + + Given the type of an iterator, returns one of the following values: + + * ``EltypeUnknown()`` if the type of elements yielded by the iterator is not known in advance. + * ``HasEltype()`` if the element type is known, and ``eltype`` would return a meaningful value. + + ``HasEltype()`` is the default, since iterators are assumed to implement ``eltype``\ . + + This trait is generally used to select between algorithms that pre-allocate a specific type of result, and algorithms that pick a result type based on the types of yielded values. + Fully implemented by: - :obj:`Range`