Using the iterors package
Author: Rich Calaway (originally for package iterators)

# Using the `iterors` package

#### Rich Calaway (originally for package `iterators`)

#### Peter Meilstrup (adapted for package `iterors`)

## Introduction

An iterator is a special type of object that generalizes the notion of a looping variable. When passed as an argument to a function that knows what to do with it, the iterator supplies a sequence of values. The iterator also maintains information about its state, in particular its current index. The `iteror` package includes a number of functions for creating iterators, starting `iteror`, which takes virtually any R object and turns it into an iterator object. The simplest function that operates on iterators is the `nextOr` function, which when given an iterator, returns the next value of the iterator. For example, here we create an iterator object from the sequence 1 to 10, and then use `nextOr` to iterate through the values:

    library(iterors)
    i1 <- iteror(1:10)
    nextOr(i1)

    ## [1] 1

    nextOr(i1)

    ## [1] 2

You can create iterators from matrices and data frames, using the `by` argument to specify whether to iterate by row or column:

    istate <- iteror(state.x77, by='row')
    nextOr(istate)

    ##         Population Income Illiteracy Life Exp Murder HS Grad Frost  Area
    ## Alabama       3615   3624        2.1    69.05   15.1    41.3    20 50708

    nextOr(istate)

    ##        Population Income Illiteracy Life Exp Murder HS Grad Frost   Area
    ## Alaska        365   6315        1.5    69.31   11.3    66.7   152 566432

Iterators can also be created from functions, in which case the iterator can be an endless source of values:

    ifun <- iteror(function(or) sample(0:9, 4, replace=TRUE))
    nextOr(ifun)

    ## [1] 3 3 2 5

    nextOr(ifun)

    ## [1] 8 6 5 2

For practical applications, iterators can be paired with `foreach` to obtain parallel results quite easily:

    > library(foreach)

    foreach: simple, scalable parallel programming from Revolution Analytics
    Use Revolution R for scalability, fault tolerance and more.
    http://www.revolutionanalytics.com

    > x <- matrix(rnorm(1e+06), ncol = 10000)
    > itx <- iteror(x, by = "row")
    > foreach(i = itx, .combine = c) %dopar% mean(i)

      [1] -0.0069652059  0.0161112989  0.0080068074 -0.0120020610  0.0017168149
      [6]  0.0139835943 -0.0078172106 -0.0024762273 -0.0031558268 -0.0072662893
     [11] -0.0055142639  0.0015717907 -0.0100842965 -0.0123601527  0.0136420084
     [16] -0.0242922105 -0.0126416949 -0.0052951152  0.0216329326 -0.0262476648
     [21]  0.0041937609  0.0121253368 -0.0110165729  0.0044267635  0.0080241894
     [26]  0.0042995539 -0.0102826632  0.0051185628 -0.0013970812 -0.0172380786
     [31]  0.0096079613  0.0046837729 -0.0080726970  0.0083781727 -0.0234620163
     [36] -0.0099883966  0.0026883628  0.0029367320  0.0205825899  0.0035303940
     [41]  0.0204990426 -0.0010804987 -0.0033665481 -0.0127492019 -0.0147443195
     [46]  0.0027046346  0.0016449793  0.0155575490 -0.0003488394 -0.0079238019
     [51]  0.0086390030 -0.0039033309  0.0168593825 -0.0067189572 -0.0009925288
     [56] -0.0162907048 -0.0059171838  0.0093806072  0.0100886929 -0.0111677408
     [61]  0.0021754963 -0.0056770907  0.0081200698 -0.0029828717 -0.0163704350
     [66]  0.0057266267 -0.0017156156  0.0214172738 -0.0141379874 -0.0126593342
     [71]  0.0087124575  0.0040231519  0.0038515673  0.0066066908  0.0023586046
     [76] -0.0044167901 -0.0090543553  0.0010806096  0.0102288061  0.0039881702
     [81] -0.0054549319 -0.0127997275 -0.0031697122 -0.0016100996 -0.0143468118
     [86]  0.0035904125 -0.0059399479  0.0085565480 -0.0159064868  0.0054120554
     [91] -0.0084420572  0.0194448129 -0.0103192553 -0.0062924628  0.0215069258
     [96]  0.0015749065  0.0109657488  0.0152237842 -0.0057181022  0.0035530715

## Some Special Iterators

The notion of an iterator is new to R, but should be familiar to users of languages such as Python. The `iterors` package includes a number of special functions that generate iterators for some common scenarios. For example, the `irnorm` function creates an iterator for which each value is drawn from a specified random normal distribution:

    library(iterors)
    itrn <- irnorm(10)
    nextOr(itrn)

    ##  [1]  0.8946316 -1.6898399  0.9420100 -1.8517304  0.2327577 -0.3617730
    ##  [7] -0.6671898 -0.4113156  0.1901028  0.1332362

    nextOr(itrn)

    ##  [1]  0.98122623 -1.32085527  1.35038361  0.04165326  0.07140616  0.24369994
    ##  [7]  0.29538358  0.58919683  0.80350873 -1.87421486

Similarly, the `irunif`, `irbinom`, and `irpois` functions create iterators which draw their values from uniform, binomial, and Poisson distributions, respectively.

We can then use these functions just as we used `irnorm`:

    itru <- irunif(10)
    nextOr(itru)

    ##  [1] 0.07721996 0.20498683 0.99213148 0.54261437 0.16174025 0.10339189
    ##  [7] 0.41159667 0.52433891 0.14157571 0.38780066

    nextOr(itru)

    ##  [1] 0.4738646 0.6090831 0.2778190 0.1662840 0.8984876 0.6992004 0.2574820
    ##  [8] 0.6859465 0.8347623 0.6066866

These random number generators are an indefinite process, but generally, iterators can come to an end. To specify what to do it the iterator ends, give `nextOr` a second argument, named `or`.

The `icount` function returns an iterator that counts starting from one:

    it <- icount(3)
    nextOr(it, NULL)

    ## [1] 1

    nextOr(it, NULL)

    ## [1] 2

    nextOr(it, NULL)

    ## [1] 3

    nextOr(it, NULL) #is now ended

    ## NULL

If you call `nextOr` in a loop you can tell nextOr to `break` to exit the loop.

    t <- icount(10)
    total <- 0
    repeat {
      total <- total + nextOr(it, break)
    }
    total # sum of 1:10

    ## [1] 0

For an index of `iteror` functions organized by task, see `vignette("categories", "iterors")`

If you are familiar with packages `iterators`/`itertools`/`itertools2`, some functions have been moved. See `vignette("cross-reference", "iterors")`

To learn how to build custom iterors, see `vignette("writing", "iterors")`