在iforever
迭代器之后vignette("writing", package="iterators")
,可以将 S3 类形式化为
setOldClass(c("abstractiter", "iter"))
然后创建一个派生类
.IForever <- setClass("IForever", contains=c("list", "abstractiter"))
使用构造函数
IForever <- function(x)
{
nextEl <- function() x
obj <- list(nextElem=nextEl)
.IForever(obj)
}
并使用
> nextElem(it)
[1] 42
> nextElem(it)
[1] 42
> unlist(as.list(it, n=6))
[1] 42 42 42 42 42 42
不过,我不确定这是否能让你获得那么多。迭代器使用闭包来提供状态,而这部分难题是由普通IForever
函数提供的,而不是 S4 类系统的某些方面。S4 的形式主义可能会导致更好定义的 API,例如,在 AbstractIterator 基类上定义的方法,但这已经仅隐含在抽象器的 S3 实现中。
一个不同的(更好的)起点是指定所需方法的参考类
.RIterator <- setRefClass("RIterator",
contains="abstractiter",
methods=list(nextElem=function() stop("not implemented")))
迭代器可以在此之上实现,
LimitIterator <- setRefClass("SleepIterator",
fields=list(times="integer", .curr="integer"),
contains="RIterator",
methods=list(
initialize=function(...) initFields(..., .curr=1L),
nextElem=function() {
if (!hasNext())
stop("StopIteration")
.curr <<- .curr + 1L
invisible(NULL)
}, hasNext=function() .curr <= times))
所以
> system.time(foreach(LimitIterator(times=8L)) %do% Sys.sleep(1L))
user system elapsed
0.052 0.000 8.057
> system.time(foreach(LimitIterator(times=8L)) %dopar% Sys.sleep(1L))
user system elapsed
0.084 0.436 1.261