An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111206/4580c888/attachment.pl>
making changes to global variables in functions
5 messages · Yev, R. Michael Weylandt, Janko Thyson +2 more
No pointer functionality in R (that I know of), but if you want to return two objects as one the standard way is to put them in a list and to return that list. Michael
On Tue, Dec 6, 2011 at 2:35 PM, Yev <kirpich at gmail.com> wrote:
I'm trying to write a function that takes several objects with many
different attributes and then changes their attributes. So what I wanted to
happen in the simplified example below is for the function to change the
attributes of the objects state1 and state2 that are passed to it. But
because stateA and stateB are local, this isn't working. Are there any easy
solutions?
e.g., if I could combine the two objects stateA and stateB into a single
object, I could return it and then assign it back to objects state1 and
state2. Or if I could pass a pointer to the original object.. But I cannot
find an easy way of doing either. ?Thanks in advance..
state1 <- list(n=100, won=0)
state2 <- list(n=100, won=0)
fight2 <- function(stateA, stateB){
? stateA$n <- 50
? stateB$n <-50
}
fight2(state1,state2)
state1$n
state2$n
? ? ? ?[[alternative HTML version deleted]]
______________________________________________ R-help at 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.
An embedded and charset-unspecified text was scrubbed... Name: not available URL: <https://stat.ethz.ch/pipermail/r-help/attachments/20111207/1c470e65/attachment.pl>
None of this pass by reference complexity is necessary. Here's how to
do it without references or environments.
A <- list(n=100,won=0)
B <- list(n=100,won=0)
f <- function(x,y)
{
nmx <- deparse(substitute(x))
nmy <- deparse(substitute(y))
x$n <-50; y$n <- 50
assign(nmx,x, pos=parent.frame())
assign(nmy,y,pos=parent.frame())
invisible(NULL)
}
## Does it work:
A <- list(n=100,won=0) B <- list(n=100,won=0) A
$n [1] 100 $won [1] 0
B
$n [1] 100 $won [1] 0
f(A,B) A
$n [1] 50 $won [1] 0
B
$n
[1] 50
$won
[1] 0
However, one may fairly ask whether doing things this way is wise --
and the answer is probably not: better to pass a list of lists, make
the changes in the passed copy, and then explicitly assign back the
results:
g <- function(l,...) {... your code ...}
z <- list(A,B)
z <- g(z)
Cheers,
Bert
On Wed, Dec 7, 2011 at 4:33 AM, Janko Thyson
<janko.thyson.rstuff at googlemail.com> wrote:
Basically, I see two options here:
1) Using environments
# Temp environment
env <- new.env(parent=emptyenv())
env$state1 <- list(n=100, won=0)
env$state2 <- list(n=100, won=0)
fight2 <- function(stateA, stateB, envir){
# ?get(stateA, envir=envir)$n <- 50
? ? # The above is what you would want to do, but
? ? # 'get<-' is not defined, so:
? ? temp <- get(stateA, envir=envir)
? ? temp$n <- 50
? ? assign(stateA, value=temp, envir=envir)
? ? # Same for stateB
? ? temp <- get(stateB, envir=envir)
? ? temp$n <- 50
? ? assign(stateA, value=temp, envir=envir)
? ? return(TRUE)
}
fight2(stateA="state1", stateB="state2", envir=env)
# Extract from environment
state1 <- env$state1
state1
state2 <- env$state2
state2
2) Using Reference Classes
# Class Def
setRefClass("State",
? ? fields=list(n="numeric", won="numeric"),
? ? methods=list(
? ? ? ? fight2=function(...){
? ? ? ? ? ? fight2Ref(.self=.self, ...)
? ? ? ? }
? ? )
)
# Set Generic
setGeneric(name="fight2Ref", signature=".self", def=function(.self, ...)
? ? standardGeneric("fight2Ref"))
# Set Method
setMethod(f="fight2Ref", signature="State",
? ? definition=function(
? ? ? ? .self,
? ? ? ? value,
? ? ? ? ...
? ? ){
? ? ? ? .self$n <- value
? ? }
)
# Note:
# You could also put the code inside 'fight2Ref' directly inside the
class def,
# but I don't want them to be too crowded, so I go by 'divide and conquer'
# Instantiate objects
state1 <- new("State", n=100, won=0)
state1
state2 <- new("State", n=100, won=0)
state2
# Apply method
state1$fight2(value=50)
state1
state2$fight2(value=50)
state2
# Back to list
stateToList <- function(obj, ...){
? ? fields <- names(getRefClass("State")$fields())
? ? out <- lapply(fields, function(x.field){
? ? ? ? obj$field(x.field)
? ? })
? ? names(out) <- fields
? ? return(out)
}
state1 <- stateToList(state1)
state1
state2 <- stateToList(state2)
state2
HTH,
Janko
On 06.12.2011 22:06, R. Michael Weylandt wrote:
No pointer functionality in R (that I know of), but if you want to return two objects as one the standard way is to put them in a list and to return that list. Michael On Tue, Dec 6, 2011 at 2:35 PM, Yev<kirpich at gmail.com> ?wrote:
I'm trying to write a function that takes several objects with many
different attributes and then changes their attributes. So what I wanted to
happen in the simplified example below is for the function to change the
attributes of the objects state1 and state2 that are passed to it. But
because stateA and stateB are local, this isn't working. Are there any easy
solutions?
e.g., if I could combine the two objects stateA and stateB into a single
object, I could return it and then assign it back to objects state1 and
state2. Or if I could pass a pointer to the original object.. But I cannot
find an easy way of doing either. ?Thanks in advance..
state1<- list(n=100, won=0)
state2<- list(n=100, won=0)
fight2<- function(stateA, stateB){
? ?stateA$n<- 50
? ?stateB$n<-50
}
fight2(state1,state2)
state1$n
state2$n
? ? ? ? [[alternative HTML version deleted]]
______________________________________________ R-help at r-project.org ?mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guidehttp://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
______________________________________________ R-help at r-project.org ?mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guidehttp://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
-- ------------------------------------------------------------------------ *Janko Thyson* janko.thyson at ku-eichstaett.de <mailto:janko.thyson at ku-eichstaett.de> Catholic University of Eichst?tt-Ingolstadt Ingolstadt School of Management Statistics and Quantitative Methods Auf der Schanz 49 D-85049 Ingolstadt www.wfi.edu/lsqm <http://www.wfi.edu/lsqm> Fon: +49 841 937-1923 Fax: +49 841 937-1965 This e-mail and any attachment is for authorized use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. ? ? ? ?[[alternative HTML version deleted]]
______________________________________________ R-help at 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.
Bert Gunter Genentech Nonclinical Biostatistics Internal Contact Info: Phone: 467-7374 Website: http://pharmadevelopment.roche.com/index/pdb/pdb-functional-groups/pdb-biostatistics/pdb-ncb-home.htm
A third option is to put your state objects in a list
and write a replacement function to modify the state
of each. E.g.,
`n<-` <- function(state, value) {
state[["n"]] <- value
state
}
n <- function(state) state[["n"]]
states <- list( list(n=100, won=0), list(n=101, won=1) )
for(i in seq_along(states)) {
n(states[[i]]) <- i*1000
}
invisible(lapply(states, dput))
# that should show:
# structure(list(n = 1000, won = 0), .Names = c("n", "won"))
# structure(list(n = 2000, won = 1), .Names = c("n", "won"))
This can make it easier to understand the flow of data.
Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
-----Original Message-----
From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Janko Thyson
Sent: Wednesday, December 07, 2011 4:34 AM
To: R. Michael Weylandt
Cc: r-help at r-project.org; Yev
Subject: Re: [R] making changes to global variables in functions
Basically, I see two options here:
1) Using environments
# Temp environment
env <- new.env(parent=emptyenv())
env$state1 <- list(n=100, won=0)
env$state2 <- list(n=100, won=0)
fight2 <- function(stateA, stateB, envir){
# get(stateA, envir=envir)$n <- 50
# The above is what you would want to do, but
# 'get<-' is not defined, so:
temp <- get(stateA, envir=envir)
temp$n <- 50
assign(stateA, value=temp, envir=envir)
# Same for stateB
temp <- get(stateB, envir=envir)
temp$n <- 50
assign(stateA, value=temp, envir=envir)
return(TRUE)
}
fight2(stateA="state1", stateB="state2", envir=env)
# Extract from environment
state1 <- env$state1
state1
state2 <- env$state2
state2
2) Using Reference Classes
# Class Def
setRefClass("State",
fields=list(n="numeric", won="numeric"),
methods=list(
fight2=function(...){
fight2Ref(.self=.self, ...)
}
)
)
# Set Generic
setGeneric(name="fight2Ref", signature=".self", def=function(.self, ...)
standardGeneric("fight2Ref"))
# Set Method
setMethod(f="fight2Ref", signature="State",
definition=function(
.self,
value,
...
){
.self$n <- value
}
)
# Note:
# You could also put the code inside 'fight2Ref' directly inside the
class def,
# but I don't want them to be too crowded, so I go by 'divide and conquer'
# Instantiate objects
state1 <- new("State", n=100, won=0)
state1
state2 <- new("State", n=100, won=0)
state2
# Apply method
state1$fight2(value=50)
state1
state2$fight2(value=50)
state2
# Back to list
stateToList <- function(obj, ...){
fields <- names(getRefClass("State")$fields())
out <- lapply(fields, function(x.field){
obj$field(x.field)
})
names(out) <- fields
return(out)
}
state1 <- stateToList(state1)
state1
state2 <- stateToList(state2)
state2
HTH,
Janko
On 06.12.2011 22:06, R. Michael Weylandt wrote:
No pointer functionality in R (that I know of), but if you want to return two objects as one the standard way is to put them in a list and to return that list. Michael On Tue, Dec 6, 2011 at 2:35 PM, Yev<kirpich at gmail.com> wrote:
I'm trying to write a function that takes several objects with many
different attributes and then changes their attributes. So what I wanted to
happen in the simplified example below is for the function to change the
attributes of the objects state1 and state2 that are passed to it. But
because stateA and stateB are local, this isn't working. Are there any easy
solutions?
e.g., if I could combine the two objects stateA and stateB into a single
object, I could return it and then assign it back to objects state1 and
state2. Or if I could pass a pointer to the original object.. But I cannot
find an easy way of doing either. Thanks in advance..
state1<- list(n=100, won=0)
state2<- list(n=100, won=0)
fight2<- function(stateA, stateB){
stateA$n<- 50
stateB$n<-50
}
fight2(state1,state2)
state1$n
state2$n
[[alternative HTML version deleted]]
______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guidehttp://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guidehttp://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
-- ------------------------------------------------------------------------ *Janko Thyson* janko.thyson at ku-eichstaett.de <mailto:janko.thyson at ku-eichstaett.de> Catholic University of Eichst?tt-Ingolstadt Ingolstadt School of Management Statistics and Quantitative Methods Auf der Schanz 49 D-85049 Ingolstadt www.wfi.edu/lsqm <http://www.wfi.edu/lsqm> Fon: +49 841 937-1923 Fax: +49 841 937-1965 This e-mail and any attachment is for authorized use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. [[alternative HTML version deleted]]