From hb at stat.berkeley.edu  Fri Nov 13 21:42:37 2009
From: hb at stat.berkeley.edu (Henrik Bengtsson)
Date: Fri, 13 Nov 2009 21:42:37 +0100
Subject: [Rd] The default behaviour of a missing entry in an environment
In-Reply-To: <6BB98E4A-8539-4C69-B754-2180AC6D7369@nyu.edu>
References: <D737F65B-A317-44C1-8421-E8DE2D0E0740@nyu.edu> 
	<4AFDB33D.5010607@stats.uwo.ca>
	<39831344-CF89-4D0C-9804-702B80D4DE4C@nyu.edu> 
	<4AFDB7DA.3080104@stats.uwo.ca>
	<6BB98E4A-8539-4C69-B754-2180AC6D7369@nyu.edu>
Message-ID: <59d7961d0911131242o1f070660m7fbe75f8501e1276@mail.gmail.com>

If you develop your own code you can add your own behavior by
"extending" the environment class.  I put "extending" in quotation
marks, because 'environment' is one of few classes you should *not*
extend from in the regular S3 (and S4?) sense, at least that was the
case a few years ago.  You can search the r-devel list about issues
when trying to do so.  One thing I remember is that it didn't work
well to save such objects.  Bla bla bla, there are workarounds for it
and the Object class in the R.oo package is one.  Here is how you can
add your protection for your own environment-like objects:

library("R.oo");
o <- Object();
o$foo
[1] NULL

setConstructorS3("PickyObject", function(...) {
  extend(Object(), "PickyObject");
});
setMethodS3("$", "PickyObject", function(this, name) {
  hasField(this, name) || throw("No such field: ", name);
  NextMethod("$");
});

po <- PickyObject();
po$foo

Error in list(`po$foo` = <environment>, ``$.PickyObject`(po, foo)` = <environmen
t>,  :

[2009-11-13 21:39:51] Exception: No such field: foo
  at throw(Exception(...))
  at throw.default("No such field: ", name)
  at throw("No such field: ", name)
  at `$.PickyObject`(po, foo)
  at po$foo

po$foo <- TRUE;
po$foo
[1] TRUE

If of any use.

/Henrik

On Fri, Nov 13, 2009 at 9:03 PM, Trishank Karthik Kuppusamy
<tk47 at nyu.edu> wrote:
>
> On Nov 13, 2009, at 2:47 PM, Duncan Murdoch wrote:
>
>> Inconsistent with what happens for lists:
>>
>> > x <- list()
>> > x$b
>> NULL
>>
>> and attributes:
>>
>> > attr(x, "b")
>> NULL
>
> Ah, I see. I would claim that the same argument for default safety should apply here too.
>
>> It is already a little stricter than $ on a list:
>>
>> > x$longname <- 1
>> > x$long
>> [1] 1
>> > e$longname <- 1
>> > e$long
>> NULL
>
> I apologize that I cannot say that this is a good idea for reasons of safety and readability.
>
>> so I supposed we could make it even more strict, but there is an awful lot of code out there that uses tests like
>>
>> if (!is.null(x <- e$b)) { do something with x }
>>
>> and all of that would break.
>
> Unfortunately, such code does make it harder to detect programming errors.
> I understand should the hands of R be tied by backwards-compatability; bad habits are hard to break.
> Thanks for your time.
>
> -Trishank
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>



[Rd] The default behaviour of a missing entry in an environment
Henrik Bengtsson