I am using R6 in a package and some of our classes are basically just lists of other classes. Currently, we are using S3 for the classes that are lists of R6 objects. This works ok, but it would be nice if we could R6 for these classes as well. The only reason we don't is that the list classes can then not be used directly with lapply and such.
In python, there are iterators:
class Counter:
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def next(self): # Python 3: def __next__(self)
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
for c in Counter(3, 8):
print c
I expect that this will not be practical in R due to how the *apply functions work.
Actually, looking at the lapply code:
> lapply
function (X, FUN, ...)
{
FUN <- match.fun(FUN)
if (!is.vector(X) || is.object(X))
X <- as.list(X)
.Internal(lapply(X, FUN))
}
<bytecode: 0x33df9d8>
<environment: namespace:base>
The as.list could be used to supply something to iterate over if an S3 as.list.my_r6_class or as.list.R6 was added like:
library(R6)
Person <- R6Class("Person",
public = list(
name = NULL,
hair = NULL,
initialize = function(name = NA, hair = NA) {
self$name <- name
self$hair <- hair
self$greet()
},
set_hair = function(val) {
self$hair <- val
},
greet = function() {
cat(paste0("Hello, my name is ", self$name, ".\n"))
}
)
)
People <- R6Class("People",
public = list(
values = list(),
initialize = function(persons) {
self$values <- persons
},
to_list = function() {
return(self$values)
}
)
)
as.list.R6 <- function(x, ...) {
if ("to_list" %in% names(x)) {
return(x$to_list())
} else {
stop("Cannot convert R6 class to list...")
}
}
joe = Person$new("joe", "shaggy")
mary = Person$new("mary", "neat")
bob = Person$new("bob", "bald")
candice = Person$new("candice", "red")
group = People$new(list(joe, mary, bob, candice))
Then lapply works:
> lapply(group, function(x) x$greet())
Hello, my name is joe.
Hello, my name is mary.
Hello, my name is bob.
Hello, my name is candice.
[[1]]
NULL
[[2]]
NULL
[[3]]
NULL
[[4]]
NULL
However, for loops do not work:
> for (x in group) {
+ x$greet()
+ }
Error in for (x in group) { : invalid for() loop sequence
I might try this with my package, but it might be useful if this behavior was part of R6.The same thing could be done for apply if dims.R6 and as.matrix.R6 were defined. Just a thought; I am not sure what other implications adding those S3s would have.
I am using R6 in a package and some of our classes are basically just lists of other classes. Currently, we are using S3 for the classes that are lists of R6 objects. This works ok, but it would be nice if we could R6 for these classes as well. The only reason we don't is that the list classes can then not be used directly with
lapply
and such.In python, there are iterators:
I expect that this will not be practical in R due to how the *apply functions work.
Actually, looking at the
lapply
code:The
as.list
could be used to supply something to iterate over if an S3as.list.my_r6_class
oras.list.R6
was added like:Then
lapply
works:However,
for
loops do not work:I might try this with my package, but it might be useful if this behavior was part of R6.The same thing could be done for
apply
ifdims.R6
andas.matrix.R6
were defined. Just a thought; I am not sure what other implications adding those S3s would have.