[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Opaque objects and Emacs documentation

From: Eli Zaretskii
Subject: Re: Opaque objects and Emacs documentation
Date: Sun, 19 Jul 2020 17:48:16 +0300

> From: Richard Stallman <rms@gnu.org>
> Cc: eliz@gnu.org, npostavs@gmail.com, emacs-devel@gnu.org
> Date: Sat, 18 Jul 2020 22:27:22 -0400
>   > > We define an accessor defsubst for each of the data it contains.  We
>   > > document its meaning.  We define a constructor function, and document
>   > > the meaning of each argument.  We manipulate them always through those
>   > > functions.  VoilĂ !
>   > > 
>   > > The subsctructure is clearly shown and yet changing it later is 
> painless.
>   > This is pretty much what I'm doing here.
>   > Only a little more complex, because there are multiple data types that 
>   > implement the same interface.
> Eli, do you think the difference is significant?

I'm probably missing something, because I don't even see the
similarity.  Let me explain.

What you, Richard, describe is a paradigm we use in several places in
Emacs.  One example is the POSITION object originally used for
describing mouse clicks.  Another example is ispell.el's
ispell-dictionary-alist.  Yet another example is the
window-configuration object manipulated by the likes of
current-window-configuration and set-window-configuration.

In these and other similar examples, we do use defsubst-type accessors
to the fields or slots of the object.  But we also have the following
important traits of the respective objects:

  . a way of creating an object of that type
  . a predicate to test whether an arbitrary Lisp value is an object
    of that type
  . a function to compare two objects of this type

Some of the objects (the first 2 examples above) have their Lisp
structure completely documented, in which case the predicate and the
comparison functions are not strictly needed (but we still provide
them, at least in some cases).  When the structure is not documented,
the predicate and the comparison functions are IMO a necessity, and
there should be either an exhaustive set of accessors for the public
fields of the object, or at least a documented list of those fields
and how to access them.

Taken together, these measures present a useful, usable, and fairly
complete description of an abstraction.

I can see none of that in project.el regarding the "project instance"
abstraction.  Not even a description of what a "project instance" is,
conceptually, or what it entails, neither in terms of the "outside
world" (i.e. the domain of its applicability), nor in terms of the
Lisp implementation.  And I can only guess what is considered the
analogy of the accessors you were alluding to, because it isn't
documented, either.  (Or maybe the idea is that none of the project's
fields are public? but then what is project-root about?)

So I don't see how these two techniques can be usefully compared, let
alone proclaimed "pretty much" the same.

The reason we were given for this lack of crucial documentation in
project.el is the desire to leave the API open to extensions.  IOW,
if, for example, we say today that a project entails a root directory,
a collection of files in that directory and its subdirectories, and
optionally a set of external tools, such as a VCS, to provide some
project-related services, then it will make it harder to add in the
future projects of a very different kind.  Which is a valid concern,
and the reason I started this thread.  Because having user commands
that allude to "project instance" without even a minimal explanation
of what that is makes our documentation of such commands almost
useless, and the question that bothers me is how to keep the quality
of our documentation at its usual high level while using these or
similar design and implementation patterns.

Bottom line: unless I'm missing something important, I think the
difference is significant, and downplaying it is not a good way of
coming up with useful solutions for this important issue.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]