[Rd] attributes of environments

Henrik Bengtsson hb at stat.berkeley.edu
Wed Jul 5 19:44:47 CEST 2006


On 7/5/06, Thomas Lumley <tlumley at u.washington.edu> wrote:
> On Wed, 5 Jul 2006, Gabor Grothendieck wrote:
>
> > On 7/5/06, Thomas Lumley <tlumley at u.washington.edu> wrote:
> >> On Wed, 5 Jul 2006, Gabor Grothendieck wrote:
> >>
> >> > On 7/5/06, Thomas Lumley <tlumley at u.washington.edu> wrote:
> >> >> On Tue, 4 Jul 2006, Gabor Grothendieck wrote:
> >> >>
> >> >> > In the code below, e is an environment which we copy to f and then
> >> >> > add attributes to e.  Now f winds up with the same attributes.
> >> >> >
> >> >> > In other words it seems that the attributes are a property of the
> >> >> > environment itself and not of the variable.  Thus it appears we
> >> >> > cannot have two environment variables that correspond to the
> >> >> > original environment but with different attributes.
> >> >>
> >> >> No, we can't. The two variables are references to the same environment,
> >> so
> >> >> they are the same.
> >> >>
> >> >> If you want the attributes to be copies rather than references then
> >> create
> >> >> a list with the environment as an element and put the attributes on the
> >> >> list.
> >> >
> >> > I realize that that is how it works but what I was really wondering was
> >> > should it work that way?
> >> >
> >>
> >> I think it really should (and this question has come up before).  If you
> >> do
> >>    e<-environment()
> >>    f<-e
> >>
> >> then there is only one object that f and e both point to. Now, since such
> >> things as S3 class and matrix dimension are implemented as attributes I
> >> think you really have to consider the attributes as part of the object
> >> [which is also how they are implemented, of course].  So if e and f are
> >> the same object they should have the same attributes.
> >
> > I don't think this follows since in the other cases modifying the
> > object also creates a copy.
>
> In cases other than environments, NULL, external pointers and weak
> references a new object is (from the language definition point of view)
> created on assignment. The fact that sometimes the actual memory
> allocation is deferred is an implementation issue.
>
> That is
>    e <- 2
>    f <- e
>
> creates two different vectors of length 1, so of course they can have
> different attributes.
>
> For environments (and for NULL, external pointers, and weak references),
> assignment does not create a new object. It creates another reference to
> the same object.  Since it is the same object, it is the same: attributes,
> values, class, etc.
>
>
> >>
> >> Another reasonable position would be to disallow attributes on
> >> environments (as we do with NULL, another reference object), but that
> >> seems extreme.
> >
> > I don't think that that would solve it because there is still the issue
> > of the class attribute which you can't disallow.
>
> Of course you can. It might be inconvenient, but it's not difficult.
>
>
> > In fact consider this:
> >
> > e <- new.env()
> > f <- e
> > class(f) <- c("myenv", "environment")
> > F <- function(x) UseMethod("F")
> > F.environment <- function(x) 1
> > F.myenv <- function(x) 2
> > F(e) # 2
> > F(f) # 2
> >
> > The point is that subclassing does not work properly with environments
>
> No, subclassing *does* work. f and e are the same object, so they have the
> same class, c("myenv", "environment"). The thing that doesn't "work" the
> way you expect is assignment:
>     f <- e
> doesn't create a new object, as it would for any other sort of object.
>
> > yet subclasses of the environment class should be possible since R
> > is supposed to be OO and I see no valid reason for exclusing environments
> > for this.  I guess in this discussion I am coming to the realization that
> > this issue really is a problem with the current way R works.
>
> It really is the way R is designed to work. Whether it is a problem or not
> is a separate issue. Environments really are references, not values, and
> they really work differently from the way most other objects work.

Yes, it about how you *try* to look at it and not how it was designed.
 I was also bitten by this a few years ago.  There are two ways to
think of 'e' and 'f' above:

 1) 'e' and 'f' are R objects (reference variables) that refers to a
common object (the environment), and applying attr(e, name) <- value
applies to the R reference object 'e' and attr(f, name) <- value
applies to the 'f' object.

 2) 'e' and 'f' are references to a common object (the environment)
and attr(e, name) <- value applies to the common environment object
and so do attr(f, name) <- value too.

Case 1) is wrong and Case 2) is correct.

If you prefer Case 1) you can wrap up your environment in a list, e.g.

  e <- list(env=new.env())
  f <- list(env=e$env)

This makes 'e' and 'f' two different object that can have different
attributes, but both e$env and f$env refers to the same environment
object.  This is the basics of the Object class in the R.oo packages.

Cheers

Henrik


>         -thomas
>
> Thomas Lumley                   Assoc. Professor, Biostatistics
> tlumley at u.washington.edu        University of Washington, Seattle
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>



More information about the R-devel mailing list