On 01/05/2012 09:18 AM, Tom Roche wrote:

William Dunlap Wed, 4 Jan 2012 22:54:41 +0000
R functions [can] use their enclosing environments to save state.

Aha!

makeStack<- function () {
   stack<- list()
   list(pop = function() {
     if (length(stack) == 0) { # get from an enclosing env.
       retval<- NULL
     } else {
       retval<- stack[[length(stack)]] # get from an enclosing env.
       stack<<- stack[-length(stack)] # assign in an enclosing env.
     }
     retval
   }, push = function(x) {
     stack[[length(stack) + 1]]<<- x # assign in an enclosing env.
     invisible(x)
   })
}

Thanks, that's quite clear.

One point is that subsetting with "[" or extending with stack[[length(stack) + 1]] triggers a copy of stack. Better to pre-allocate

   stack <- vector("list", 100)
   curr <- 0L

and fill, e.g., push with

  curr <<- curr + 1L
  stack[[curr]] <<- x

plus bounds check and perhaps growth when necessary.


There are various encapsulations of this method in R. See, e.g.,
"reference classes" or the "proto" package.

I can't see a reference-class implementation, but I did find

Probably Bill was pointing to ?ReferenceClasses. My attempt at implementing a stack as a reference class led, ironically, to copying issues anyway (below; maybe there's a different implementation?)

Efficient R programming usually involves operations on vectors, rather than the iteration implied by a stack. This might change your conclusion that a stack-based solution is appropriate.

Martin

Reference class implementation

.Stack <- setRefClass("Stack",
    fields=list(stack="list", curr="integer"),
    methods=list(
      initialize=function(stackSize=100L, ...) {
          callSuper(stack=vector("list", stackSize), curr=0L, ...)
      },
      push=function(val) {
          curr <<- curr + 1L
          if (curr > length(stack))
              ## double size; could be a bad choice
              length(stack) <<- 2L * length(stack)
          stack[[curr]] <<- val
          invisible(val)
      },
      pop=function() {
          if (curr == 0L)
              NULL                      # sentinel: empty
          else {
              val <- stack[[curr]]
              curr <<- curr - 1L
              val
          }
      },
      show=function() {
          cat("Class:", class(.self), "\n")
          cat("current size:", .self$curr, "\n")
          cat("maximum size:", length(.self$stack), "\n")
          if (.self$curr) {
              cat("head:\n")
              print(.self$stack[[1L]])
          }
      }))

and then

> stack <- .Stack$new()
> tracemem(stack$stack)
[1] "<0x1afc090>"
> stack$push(10)
tracemem[0x1afc090 -> 0x9283a0]: <Anonymous>
tracemem[0x9283a0 -> 0xb96450]: <Anonymous> <Anonymous>
> stack$push(10)
tracemem[0xb96450 -> 0x1b2a7d0]: <Anonymous> <Anonymous>
> stack
Class: Stack
current size: 2
maximum size: 100
head:
[1] 10
> while (!is.null(val <- stack$pop()))
+     cat("val:", val, "\n")
val: 10
val: 10


https://stat.ethz.ch/pipermail/r-help/2010-March/230353.html (slightly edited)
[Subject:] [R] Stack type
[From:] Gabor Grothendieck ggrothendieck at gmail.com
[Date:] Tue Mar 2 14:33:43 CET 2010

library(proto)
Stack<- proto(new = function(.) proto(Stack,
   stack = NULL,
   push = function(., el) { .$stack<- c(list(el), .$stack) },
   pop = function(.) {
       stopifnot(length(.$stack)>  0)
     out<- .$stack[[1]]
     .$stack[[1]]<- NULL
     out
}))

mystack<- Stack$new()
mystack$push( 1 )
mystack$push( letters )
mystack$pop()
mystack$pop()
mystack$pop() # gives an error

Thanks again! Tom Roche<tom_ro...@pobox.com>

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.


--
Computational Biology
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109

Location: M1-B861
Telephone: 206 667-2793

______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to