Generic "classes" inside R

data-structures, generics, r, stack

Solution

This is a simpler version of the stack implementation @GSee references that avoids using any of the formal object-orientation systems available in R. Simplification proceeds from the fact that all functions in R are closures and functions created during a function call are bound to the environment created for that call.

new_stack <- function() {
    stack <- vector()
    push <- function(x) stack <<- c(stack, x)
    pop <- function() {
        tmp<-tail(stack, 1)
        stack<<-stack[-length(stack)]
        return(tmp)
    }
    structure(list(pop=pop, push=push), class='stack')
}

x <- new_stack()
x$push(1:3)
x$pop()
# [1] 3
x$pop()
# [1] 2

Here's an S4 implementation, for comparison.

setClass('Stack', 
         representation(list='list', cursor='numeric'),  # type defs
         prototype(list=list(), cursor=NA_real_))        # default values

setGeneric('push', function(obj, ...) standardGeneric('push'))
setMethod('push', signature(obj='Stack'), 
    function(obj, x) {
        obj@list <- c(x, obj@list)
        obj
})

setGeneric('pop', function(obj, ...) standardGeneric('pop'))
setMethod('pop', signature(obj='Stack'),
    function(obj) {
        obj@cursor <- obj@list[[1]]
        obj@list <- obj@list[-1]
        obj
    }
)

x <- new('Stack')

# cursor is empty to start
x@cursor
#[1] NA

# add items
x <- push(x, 1)
x <- push(x, 2)

# pop them (move next item to cursor, remove from list)
x <- pop(x)
x@cursor
# [1] 2
x <- pop(x)
x@cursor
# [1] 1

Problem

I have written a stack "class" with the following functions: `add`, `push`, `pop`, `size`, `isEmpty`, `clear` (and some more). I'd like to use this "class" as a generic in R, so I may create multiple instances of stacks within my script. How do I go about doing this? (I have class in quotes because my stack functions are written in a different script (not necessarily the definition of a class per se) Thanks in advance ``` list <- "" cursor = 0 #Initializes stack to empty stack <- function(){ list <- c() cursor = -1 assign("list",list,.GlobalEnv) assign("cursor",cursor,.GlobalEnv) } #Where item is a item to be added to generic list push <- function(item){ if(size(list) == 0){ add(item, -1) }else{ add(item, 0) } assign("list",list,.GlobalEnv) } ```

Original source

Related problems