[R] Question on closure (lexical scoping) and encapsulation

Douglas Bates bates at stat.wisc.edu
Tue Jun 13 22:48:22 CEST 2000


Aleksey Naumov <naumov at acsu.buffalo.edu> writes:

> I have two related questions about scoping and data encapsulation.

> One is fairly specific - I am looking at "scoping.R" which is used
> in demo(scoping) - it's an example of lexical scoping and
> encapsulation.  Where is the 'total' stored? It is not an attribute
> in 'ross' or 'robert' however, functions like balance() have access
> to it.  Is it more or less like a private class member in C++, so
> that it's not possible to access it from outside of class?

Sort of.  The functions like ross$deposit, ross$withdraw, and
ross$balance all share a common environment, which is where the total
is stored.
 > demo(scoping)
 ...
 > environment(ross$balance)
 <environment: 0x40b057ec>
 > environment(ross$withdraw)
 <environment: 0x40b057ec>
 > environment(ross$deposit)
 <environment: 0x40b057ec>
 > objects(env = environment(ross$balance))
 [1] "total"

I find it helpful to think of the contents of the environment as like
the instance variables in a C++ or Java class.  The functions defined
so they share that environment are then like methods.

The analogy is not perfect because the structure of elements of a
class is not required to be consistent in R.  The class structure is
more informal than that of C++ or Java.

> Or is it possible to access it in some way?

You can get access to objects in that environment but you have to use
functions like get and assign to manipulate them.

 > get("total", env = environment(ross$balance))
 [1] 120

> The second one is more general - what is the best way to encapsulate
> some
> user data with an object like a data frame? I'd like to keep a few user
> attributes with a data frame... I can think of 3 possibilities, but I
> don't know if there's a good and reliable standard way:
>     - I tried using attributes(), but found out that subset() gets rid
> of
> user attributes and didn't see an easy way to reset them on a subsetted
> frame
> (doing it one by one is not an option, and mostattributes() doesn't seem
> to
> be there anymore)
>     - Something like the example used in 'scoping.R'
>     - Using class()? Documentation for class() talks about providing
> methods
> for generic functions, but I didn't see an example of accessing
> user-defined
> data members/attributes.

If you have the same types of information that you want to store with
each instance of the data frame then you would usually extend the
data.frame class.  Your constructor would first create a data frame,
then add the attributes that you want, then change the class to
something like c("ExtendedFrame", "data.frame") and return the object.

If you find that subset strips the attributes that you need then you
could create a subset.ExtendedFrame that saved a local copy of those
attributes, did the call to subset.data.frame (perhaps through
NextMethod), and restored the attributes before returning the result.

>From a quick glance at subset.data.frame, I suspect it is actually the
subscripting function "[" that is dropping the attributes you want to
retain.

See chapter 4 of Venables and Ripley's "S Programming" for a more
complete description of how the class structure works.   Please be
aware that the material in their chapter 5, "New-style Classes", does
not apply to R.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._



More information about the R-help mailing list