--- title: "Using the `iterors` package" output: rmarkdown::html_vignette author: - Rich Calaway (originally for package `iterators`) - Peter Meilstrup (adapted for package `iterors`) vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{Using the `iterors` package} %\VignetteEncoding{UTF-8} --- ## 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: ```{R ex1} library(iterors) i1 <- iteror(1:10) nextOr(i1) nextOr(i1) ``` You can create iterators from matrices and data frames, using the `by` argument to specify whether to iterate by row or column: ```{R ex2} istate <- iteror(state.x77, by='row') nextOr(istate) nextOr(istate) ``` Iterators can also be created from functions, in which case the iterator can be an endless source of values: ```{R ex3} ifun <- iteror(function(or) sample(0:9, 4, replace=TRUE)) nextOr(ifun) nextOr(ifun) ``` For practical applications, iterators can be paired with `foreach` to obtain parallel results quite easily: ```r > library(foreach) ``` ``` foreach: simple, scalable parallel programming from Revolution Analytics Use Revolution R for scalability, fault tolerance and more. http://www.revolutionanalytics.com ``` ```r > 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: ```{R ex5} library(iterors) itrn <- irnorm(10) nextOr(itrn) nextOr(itrn) ``` 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`: ```{R ex6} itru <- irunif(10) nextOr(itru) nextOr(itru) ``` 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: ```{R ex7} it <- icount(3) nextOr(it, NULL) nextOr(it, NULL) nextOr(it, NULL) nextOr(it, NULL) #is now ended ``` If you call `nextOr` in a loop you can tell nextOr to `break` to exit the loop. ```{R ex8} t <- icount(10) total <- 0 repeat { total <- total + nextOr(it, break) } total # sum of 1:10 ``` For an index of `iteror` functions organized by task, see [`vignette("categories", "iterors")`](https://crowding.github.io/iterors/articles/categories.html) If you are familiar with packages `iterators`/`itertools`/`itertools2`, some functions have been moved. See [`vignette("cross-reference", "iterors")`](https://crowding.github.io/iterors/articles/cross-reference.html) To learn how to build custom iterors, see [`vignette("writing", "iterors")`](https://crowding.github.io/iterors/articles/writing.html)