From ggrothendieck at gmail.com  Wed Jul  5 20:14:15 2006
From: ggrothendieck at gmail.com (Gabor Grothendieck)
Date: Wed, 5 Jul 2006 14:14:15 -0400
Subject: [Rd] attributes of environments
In-Reply-To: <59d7961d0607051044x6c15463ckd6cfafd4995c2bbd@mail.gmail.com>
References: <971536df0607042012h43eb1581n418e9cddfe3a51bb@mail.gmail.com>
	<Pine.LNX.4.64.0607050857440.32591@homer22.u.washington.edu>
	<971536df0607050910w2a35e6ecxef5dec5c41a781e3@mail.gmail.com>
	<Pine.LNX.4.64.0607050911380.32591@homer22.u.washington.edu>
	<971536df0607050939r11dbdb93g6186550477e78d92@mail.gmail.com>
	<Pine.LNX.4.64.0607050947290.32591@homer22.u.washington.edu>
	<59d7961d0607051044x6c15463ckd6cfafd4995c2bbd@mail.gmail.com>
Message-ID: <971536df0607051114v5b80b97cnb6ad68cfd0a0a121@mail.gmail.com>

On 7/5/06, Henrik Bengtsson <hb at stat.berkeley.edu> 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 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.

I think what you mean is that case 2 is how it works but from
the viewpoint of desirability in terms of design, case 2 seems
inconsistent with oo principles since subclassing does not work
properly.

>
> 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)

I realize that this is how a number of packages, such as tcltk, work
to circumvent the design problem but what one really wants is the
ability to define a subclass of environment directly -- not create a new
class and then define a subclass of that new class.  In particular, one wants
all the existing environment methods to work on the subclass
and they don't unless you redefine them all.  OO is about reusing
existing functionality via inheritance.

>
> 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.



[Rd] attributes of environments
Gabor Grothendieck