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

From: Duncan Murdoch <murdoch_at_stats.uwo.ca>
Date: Fri 10 Jun 2005 - 05:51:46 EST

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



R-help@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html Received on Fri Jun 10 05:55:50 2005

This archive was generated by hypermail 2.1.8 : Fri 03 Mar 2006 - 03:32:28 EST