72 lines
1.6 KiB
R
Raw Normal View History

2025-01-12 00:52:51 +08:00
library(iterators)
# This example was originally written and contributed
# by Hadley Wickham, with minor modifications by
# Revolution Analytics
# Define a hasNext generic function
hasNext <- function(obj, ...) {
UseMethod('hasNext')
}
# Define a hasNext method for the "ihasNext" class
hasNext.ihasNext <- function(obj, ...) {
obj$hasNext()
}
# This function takes an iterator and returns an iterator that supports
# the "hasNext" method. This simplifies manually calling the "nextElem"
# method of the iterator, since you don't have to worry about catching
# the "StopIteration" exception.
ihasNext <- function(it) {
it <- iter(it)
# If "it" already has a hasNext function, return it unchanged
if (!is.null(it$hasNext))
return(it)
cache <- NULL
has_next <- NA
nextEl <- function() {
if (!hasNx())
stop('StopIteration', call.=FALSE)
# Reset the "has_next" flag and return the value
has_next <<- NA
cache
}
hasNx <- function() {
# Check if you already know the answer
if (!is.na(has_next))
return(has_next)
# Try to get the next element
tryCatch({
cache <<- nextElem(it)
has_next <<- TRUE
},
error=function(e) {
if (identical(conditionMessage(e), 'StopIteration')) {
has_next <<- FALSE
} else {
stop(e)
}
})
has_next
}
obj <- list(nextElem=nextEl, hasNext=hasNx)
class(obj) <- c('ihasNext', 'abstractiter', 'iter')
obj
}
# Create a "counting" iterator that has a hasNext method
it <- ihasNext(icount(3))
# Print the values of the iterator without the need for error handling
while (hasNext(it))
print(nextElem(it))