Threading state
In S3 the challenge is to return a value and modify the object.
new_stack <- function(items = list()) {
structure(list(items = items), class = "stack")
}
push <- function(x, y) {
x$items <- c(x$items, list(y))
x
}
No problem with that, but what about when we want to pop a value? We need to return two things.
pop <- function(x) {
n <- length(x$items)
item <- x$items[[n]]
x$items <- x$items[-n]
list(item = item, x = x)
}
The usage is a bit awkward:
s <- new_stack()
s <- push(s, 10)
s <- push(s, 20)
out <- pop(s)
# Update state:
s <- out$x
print(out$item)
#> [1] 20
In python and other languages we have structured binding to make this less awkward. R has the {zeallot} package. For more, see this vignette:
However, this is all easier in R6 due to the reference semantics!
Stack <- R6::R6Class("Stack", list(
items = list(),
push = function(x) {
self$items <- c(self$items, x)
invisible(self)
},
pop = function() {
item <- self$items[[self$length()]]
self$items <- self$items[-self$length()]
item
},
length = function() {
length(self$items)
}
))
s <- Stack$new()
s$push(10)
s$push(20)
s$pop()
#> [1] 20