[R] How to change the value of a class slot

Duncan Murdoch murdoch at stats.uwo.ca
Thu Jun 9 21:51:46 CEST 2005


On 6/9/2005 3:04 PM, Ross Boylan wrote:
> On Wed, 2005-06-08 at 09:13 +0200, Uwe Ligges wrote:
> [extensive deletions.  Discussion concerned my desire to have a function change the value
>  of an object in a way that had effects outside of the function, without returning the object.]
> 
>> >>You have to think about scoping rules and it 
>> >>will be clear that the approach you are expecting is not a clean one in S.
>> > 
>> > Could you say a bit more about that?  
>> 
>> I meant the following simple example (not related to any object oriented 
>> programming from the S point of view, but maybe well from your point of 
>> view?):
>> 
>> Say you want a function foo() that simply incements the argument:
>> 
>> a <- 1
>> foo(a)
>> a # now is 2
>> 
>> But what happens if there is (more than) one "a" (in different 
>> environments), but no "a" in the environment foo(a) is called from. 
>> Which "a" do you want to change in this case? Seems to be rather dangerous.
>> 
>> Uwe Ligges
>> 
> I believe your example assumes that foo is updating the outer a by
> "cheating" and directly modifying enclosing environments.  (I figure it
> also needs to get the name of its actual argument to do this, which
> would also involve slightly dirty tricks.) This does seem to be the only
> way to do it in standard R.
> 
> In contrast, I wanted something like
> foo<-function(formalArg){ 
>   formalArg <- new value
>   return something  else
> }
> so that if I call foo(a), a has the new value after the call.
> Unfortunately for me, that doesn't work.  Call-by-value semantics imply
> that it can't.

Here are some dirty ways to do it:

 > foo <- function(FormalArg, value) {
+   assign(as.character(substitute(FormalArg)), value, 
envir=sys.frame(sys.parent()))
+ }
 > x
Error: Object "x" not found
 > foo(x, 4)
 > x
[1] 4

That one does the assignment in the caller's frame, not necessarily the 
place that FormalArg was found.  If you want to change a value that you 
know exists, you could do something like this:

which.env <- function(name, envir = sys.frame(sys.parent())) {
     if (!exists(name, envir)) stop('not found')
     result <- envir
     while (!is.null(result) && !exists(name, result, inherits = FALSE))
       result <- parent.env(result)
     return(result)
}

foo <- function(FormalArg, value) {
     name <- as.character(substitute(FormalArg))
     assign(name, value, which.env(name, sys.frame(sys.parent())))
}

Duncan Murdoch




More information about the R-help mailing list