[R] I don't understand this

Richard A. O'Keefe ok at cs.otago.ac.nz
Wed Sep 3 04:14:19 CEST 2003

Thomas Lumley <tlumley at u.washington.edu> wrote:
	I would have said that the behavior of
	   (if (cond) names else dim)(x) <- 10
	is undefined in the S language, along with things like the order of
	evaluation of the apply functions.
The thing is, it would make perfect sense for
    (if (cond) f else g)(x) <- e
to have the effect of
    (if (cond) f(x) <- e else g(x) <- e)	    

In fact, I've used two programming languages where the analogue of
this _did_ work, and a third where it didn't but using only published
interfaces could very easily be made to work.

Another assignment-related thing I'm not clear on is what
    f(x) <<- e
is supposed to do.
    f(x) <- e
is equivalent to
    x <- "f<-"(x, value=e)
    x <<- e
assigns to x in the next outer environment,
but a simple macro-expansion of
    f(x) <<- e
    x <<- "f<-"(x, value=e)
may have the nasty effect of writing to an outer x a value derived from
an inner one.

Now, that seems to be exactly what happens in R:

> x <- c(1,2,3)
> f <- function(x) x[2] <<- x
> f(77)
> x
[1] 77 77

While the documentation and source code _could_ tell me whether this
is intentional, as far as I can tell (and I have, needless to say,
looked) they _don't_.

Now, despite its misleading opening screen (which says that the
target of an assignment is "a variable name (possibly quoted)",
?"<<-" goes on to say that
     In all the assignment operator expressions, `x' can be a name or
     an expression defining a part of an object to be replaced (e.g.,
     `z[[1]]').  The name does not need to be quoted, though it can be.
(the arrows are my emphasis.)  So it's explict that f(x) <<- e is
*supposed* to be allowed and I don't need to ask about that.

The question is, what is f(x) <<- e supposed to do when there is an
x in the current environment as well as one in an outer environment?
It doesn't make much sense to fetch from one variable and store into
the other, but that's what R actually does.  Is that really what's
*supposed* to happen?

It would be perfectly possible to make f(x) <<- e use the same
variable in both places, and since the form is accepted by R,
I expected it to work that way.

Perhaps the simplest alternative that would still allow this form
to be used in non-confusing cases would be to issue an error message
if x is defined in the local environment; if it isn't, the simple macro
expansion will work just fine.

> x <- c(1,2,3)
> f <- function(y) x[2] <<- y
> f(77)
> x
[1]  1 77  3

This example works as ?"<<-" might lead one to expect.

More information about the R-help mailing list