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

Reply via email to