Re: [Rd] S4 accessors

From: Ross Boylan <ross_at_biostat.ucsf.edu>
Date: Wed 27 Sep 2006 - 22:01:37 GMT

I'm trying to understand what the underlying issues are here--with the immediate goal of how that affects my design and documentation decisions.

On Wed, Sep 27, 2006 at 02:08:34PM -0400, John Chambers wrote:
> Seth Falcon wrote:
> > John Chambers <jmc@r-project.org> writes:
> >
> >
> >> There is a point that needs to be remembered in discussions of
> >> accessor functions (and more generally).
> >>
> >> We're working with a class/method mechanism in a _functional_
> >> language. Simple analogies made from class-based languages such as
> >> Java are not always good guides.
> >>
> >> In the example below, "a function foo that only operates on that
> >> class" is not usually a meaningful concept in R.

The sense of "meaningful" here is hard for me to pin down, even with the subsequent discussion.

I think the import is more than formal: R is not strongly typed, so you can hand any argument to any function and the language will not complain.

> >>
> >
> > If foo is a generic and the only method defined is for class Bar, then
> > the statement seems meaningful enough?
> >
>
> This is not primarily a question about implementation but about what the
> user understands. IMO, a function should have an intuitive meaning to
> the user. Its name is taking up a "global" place in the user's brain,
> and good software design says not to overload users with too many
> arbitrary names to remember.

It's true that clashing uses of the same name may lead to confusion, but that need not imply that functions must be applicable to all objects. Many functions only make sense in particular contexts, and sometimes those contexts are quite narrow.

One of the usual motivations for an OO approach is precisely to limit the amount of global space taken up by, for example, functions that operate on the class (global in both the syntactic sense and in the inside your brain sense). Understanding a traditional OO system, at least for me, is fundamentally oriented to understanding the objects first, with the operations on them as auxiliaries. As you point out, this is just different from the orientation of a functional language, which starts with the functions.

>
> To be a bit facetious, if "flag is a slot in class Bar, it's really not
> a good idea to define the accessor for that slot as
> flag <- function(object)object@flag
>
> Nor is the situation much improved by having flag() be a generic, with
> the only method being for class Bar. We're absconding with a word that
> users might think has a general meaning. OK, if need be we will have
> different flag() functions in different packages that have _different_
> intuitive interpretations, but it seems to me that we should try to
> avoid that problem when we can.
>
> OTOH, it's not such an imposition to have accessor functions with a
> syntax that includes the name of the slot in a standardized way:
> get_flag(object)
> (I don't have any special attachment to this convention, it's just there
> for an example)

I don't see why get_flag differs from flag; if "flag" lends itself to multiple interpretations or meanings, wouldn't "get_flag" have the same problem?

Or are you referring to the fact that "flag" sounds as if it's a verb or action? That's a significant ambiguity, but there's nothing about it that is specific to a functional approach.

>
> >
> >> Functions are first-class objects and in principle every function
> >> should have a "function", a purpose. Methods implement that purpose
> >> for particular combinations of arguments.
> >>

If this is a claim that every function should make sense for every object, it's asking too much. If it's not, I don't really see how a function can avoid having a purpose. The purpose of accessor functions is to get or set the state of the object.

> >> Accessor functions are therefore a bit anomalous.
> >>
> >
> > How? A given accessor function has the purpose of returning the
> > expected data "contained" in an instance. It provides an abstract
> > interface that decouples the structure of the class from the data it
> > needs to provide to users.
> >
>
> See above. That's true _if_ the name or some other syntactic sugar
> makes it clear the this is indeed an accessor function, but not otherwise.

Aside from the fact that I don't see why get_flag is so different from flag, the syntactic sugar argument has another problem. The usually conceived purpose of accessors is to hide from the client the internals of the object. To take an example that's pretty close to one of my classes, I want startTime, endTime, and duration. Internally, the object only needs to hold 2 of these quantities to get the 3rd, but I don't want the client code to be aware of which choice I made. In particular, I don't what the client code to change from duration to get_duration if I switch to a representation that stored the duration as a slot.

Ross



R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Thu Sep 28 08:17:20 2006

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.1.8, at Thu 28 Sep 2006 - 15:30:10 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.