Create an Iterator object, where the user defines a sequence and a
set of initial values, and then calls yield_next()
to generate the
next element of the sequence. Iterator
s are R environments, which means
they are modified in place, even when passed as arguments to functions.
To make a copy of an Iterator that can be modified separately, see clone()
.
Iterator(result, initial, yield)
result | R expression to run each time 'yield_next' is called |
---|---|
initial | named list or vector; declare and initialize every variable that appears in 'result' |
yield | variable to yield when 'yield_next()' is called |
An environment object of S3 type Iterator
The expression to be evaluated can include constant values not defined in
$initial
as long as they are defined in the enclosure of where yield_next() is called,
not where the Iterator is created.
These values will not vary from iteration to
iteration (unless you do something strange in the code, like including <<- in $result
.)
#Create the Collatz sequence starting with 50 and print out the first 30 elements collatz <- Iterator({ if (n %% 2 == 0) n <- n / 2 else n <- n*3 + 1 }, initial = c(n = 50), yield = n) seq <- yield_more(collatz, 30) # If you want to define the expression outside the Iterator, use [quote()] and `!!`: expr <- quote(if (n %% 2 == 0) n <- n / 2 else n <- n*3 + 1) collatz <- Iterator(!!expr, c(n = 50), n) # using objects defined outside `$initial`: # Note that `n` in `$initial` overrides the global `n` m <- 100 n <- 10 it <- Iterator({out <- n + m}, initial = c(n = -10), yield = out) yield_next(it)#> [1] 90# environments are modified in place, so be aware: it <- Iterator({m <- m + 1}, c(m = 0), m) other <- it yield_next(it)#> [1] 1#> [1] 1