Re: [R] [newbie] stack operations, or functions with side effects (or both)
There is a crude implementation of stacks in 'S Poetry' (available on www.burns-stat.com). I haven't looked at it, but I'd guess that code would work in R as well. On 04/01/2012 21:22, Tom Roche wrote: summary: Specifically, how does one do stack/FIFO operations in R? Generally, how does one code functions with side effects in R? details: I have been a coder for years, mostly using C-like semantics (e.g., Java). I am now trying to become a scientist, and to use R, but I don't yet have the sense of good R and R idiom (i.e., expressions that are to R what (e.g.) the Schwartzian transform is to Perl). I have a data-assimilation problem for which I see a solution that wants a stack--or, really, just a pop(...) such that * s- c(1:5) * print(s) [1] 1 2 3 4 5 * pop(s) [1] 1 * print(s) [1] 2 3 4 5 but in fact I get pop(s) Error: could not find function pop and Rseek'ing finds me nothing. When I try to write pop(...) I get pop1- function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + vector_arg- vector_arg[2:lv] + ret + } pop1(s) [1] 1 print(s) [1] 1 2 3 4 5 i.e., no side effect on the argument pop2- function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + assign(vector_arg, vector_arg[2:lv]) + return(ret) + } pop2(s) [1] 1 print(s) [1] 1 2 3 4 5 ditto :-( What am I missing? * Is there already a stack API for R (which I would expect)? If so, where? * How to cause the desired side effect to the argument in the code above? TIA, Tom Rochetom_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. -- Patrick Burns pbu...@pburns.seanet.com twitter: @portfolioprobe http://www.portfolioprobe.com/blog http://www.burns-stat.com (home of 'Some hints for the R beginner' and 'The R Inferno') __ 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.
Re: [R] [newbie] stack operations, or functions with side effects (or both)
William Dunlap Wed, 4 Jan 2012 22:54:41 + 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. 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 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.
Re: [R] [newbie] stack operations, or functions with side effects (or both)
On 01/05/2012 09:18 AM, Tom Roche wrote: William Dunlap Wed, 4 Jan 2012 22:54:41 + 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 Rochetom_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.
Re: [R] [newbie] stack operations, or functions with side effects (or both)
Thanks for the improvements. The main point in my original post was that altering the arguments of a function is a really bad thing to do in R (except when using replacement functions). A function that alters other objects in the caller's environment is also really bad. By bad I mean that such functions are not safe to use because they alter things that are not theirs to alter and thus can lead to incorrect results in a rather unpredictable (to the user) fashion. Objects with state, like stacks, are less bad but they can cause problems when you decide to parallelize your code (you need to synchronize the state across the copies of the code). The best code sticks with the functional paradigm that most R functions have: data flows from a function's arguments to its return value with no side effects or state changes. None of the above concerns cpu efficiency. It is about the programming efficiency of having reliable reusable code. Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com -Original Message- From: r-help-boun...@r-project.org [mailto:r-help-boun...@r-project.org] On Behalf Of Martin Morgan Sent: Thursday, January 05, 2012 10:38 AM To: r-help@r-project.org; Tom Roche Subject: Re: [R] [newbie] stack operations, or functions with side effects (or both) On 01/05/2012 09:18 AM, Tom Roche wrote: William Dunlap Wed, 4 Jan 2012 22:54:41 + 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
Re: [R] [newbie] stack operations, or functions with side effects (or both)
do s[1] and s[-1] do what you're looking for? those are just to display... if you want to change s, you need to reassign it or fiddle with namespacing. however, I'd say it is better to write R code as though data structures are immutable until you explicitly re-assign them rather than trying to deal with side effects and state... pop - function(vec){ + print(vec[1]) + print(vec[-1]) + return(vec[-1]) +} s - 1:5 s - pop(s) [1] 1 [1] 2 3 4 5 s [1] 2 3 4 5 On Wed, Jan 4, 2012 at 1:22 PM, Tom Roche tom_ro...@pobox.com wrote: summary: Specifically, how does one do stack/FIFO operations in R? Generally, how does one code functions with side effects in R? details: I have been a coder for years, mostly using C-like semantics (e.g., Java). I am now trying to become a scientist, and to use R, but I don't yet have the sense of good R and R idiom (i.e., expressions that are to R what (e.g.) the Schwartzian transform is to Perl). I have a data-assimilation problem for which I see a solution that wants a stack--or, really, just a pop(...) such that * s - c(1:5) * print(s) [1] 1 2 3 4 5 * pop(s) [1] 1 * print(s) [1] 2 3 4 5 but in fact I get pop(s) Error: could not find function pop and Rseek'ing finds me nothing. When I try to write pop(...) I get pop1 - function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + vector_arg - vector_arg[2:lv] + ret + } pop1(s) [1] 1 print(s) [1] 1 2 3 4 5 i.e., no side effect on the argument pop2 - function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + assign(vector_arg, vector_arg[2:lv]) + return(ret) + } pop2(s) [1] 1 print(s) [1] 1 2 3 4 5 ditto :-( What am I missing? * Is there already a stack API for R (which I would expect)? If so, where? * How to cause the desired side effect to the argument in the code above? TIA, 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. [[alternative HTML version deleted]] __ 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.
Re: [R] [newbie] stack operations, or functions with side effects (or both)
R functions should not alter their arguments, except for 'replacement' functions that are called on the left side of an assignment operators (e.g., x[1]-10 calls the replacement function `[-`). R functions cam use their enclosing environments to save state. E.g., the following makeStack function make an object whose state (consisting of the variable 'stack') is accessible from the functions in the list that it returns: 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) }) } The following calls make two stack objects and use them: aStack - makeStack() anotherStack - makeStack() aStack$push(one) anotherStack$push(as.roman(1)) anotherStack$push(as.roman(2)) aStack$push(two) aStack$push(three) anotherStack$pop() [1] II anotherStack$pop() [1] I anotherStack$pop() NULL aStack$pop() [1] three aStack$pop() [1] two There are various encapsulations of this method in R. See, e.g., reference classes or the proto package. Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com -Original Message- From: r-help-boun...@r-project.org [mailto:r-help-boun...@r-project.org] On Behalf Of Tom Roche Sent: Wednesday, January 04, 2012 1:23 PM To: r-help@r-project.org Subject: [R] [newbie] stack operations, or functions with side effects (or both) summary: Specifically, how does one do stack/FIFO operations in R? Generally, how does one code functions with side effects in R? details: I have been a coder for years, mostly using C-like semantics (e.g., Java). I am now trying to become a scientist, and to use R, but I don't yet have the sense of good R and R idiom (i.e., expressions that are to R what (e.g.) the Schwartzian transform is to Perl). I have a data-assimilation problem for which I see a solution that wants a stack--or, really, just a pop(...) such that * s - c(1:5) * print(s) [1] 1 2 3 4 5 * pop(s) [1] 1 * print(s) [1] 2 3 4 5 but in fact I get pop(s) Error: could not find function pop and Rseek'ing finds me nothing. When I try to write pop(...) I get pop1 - function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + vector_arg - vector_arg[2:lv] + ret + } pop1(s) [1] 1 print(s) [1] 1 2 3 4 5 i.e., no side effect on the argument pop2 - function(vector_arg) { + length(vector_arg) - lv + vector_arg[1] - ret + assign(vector_arg, vector_arg[2:lv]) + return(ret) + } pop2(s) [1] 1 print(s) [1] 1 2 3 4 5 ditto :-( What am I missing? * Is there already a stack API for R (which I would expect)? If so, where? * How to cause the desired side effect to the argument in the code above? TIA, 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. __ 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.