Lazy range class in R

46 Views Asked by At

In R, ranges are immediately evaluated into vectors:

> 1:3
[1] 1 2 3

Is there an idiomatic way to construct ranges without evaluating them into lists, or must I define it myself?

setClass(
  "Range",
  representation(
    start = "numeric",
    stop = "numeric"
  )
)

Range <- function(start, stop) {
  new("Range", start = start, stop = stop)
}

setMethod("show", "Range", function(object) {
  cat(paste0(object@start, ":", object@stop, "\n"))
})
1

There are 1 best solutions below

0
Ben Bolker On

There is an iterators package on CRAN, which might be what you're looking for. However, while it has a "counting iterator" icount(), there's not an obvious way to make it start anywhere other than 0 ... you could hack it by messing with the internal environment, but it would be better to construct your own range iterator (which would be basically be rolling it yourself again).

The other thing to be aware of is that sequences constructed with : are already stored as ALTREP ("alternative representation") objects, so they're much smaller than you think:

vec <- 1:1e10
lobstr::obj_size(vec)
680 B

(however, if you try to print this object it will print the first getOption("max.print") elements - it won't resist evaluating itself ...)


To be slightly pedantic, I would say that ranges aren't "immediately evaluated into vectors", thanks to ALTREP. However, they are evaluated if you print them ...