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

Re: Sealed as Source Annotation



To more directly state my purpose in asking about internal vs.
external annotations, I am seeking to understand the pros and cons in
abstract terms. As Dylan and Java are the only languages I am at all
familar with that contain the sealing/final class concept, I am asking
in that context. I seek enlightenment not a change to either language.

On Fri, 14 Jul 2000 12:31:06 +1200, Bruce Hoult <bruce@hoult.org> wrote:
>You will know, but I expect most Java programmers won't, that a sealed 
>class in Dylan *can* be extended, but only within the same compile unit.

Actually, I did not know this. As I said in my previous post, all I
know about Dylan came from reading (in 1992) Apple's 1992 book "Dylan:
an Object-Oriented Dynamic Language". (I have largely been a sporadic
lurker to Dylan since around 1994.) In Apple's book, the only mention
of sealing concerned sealing classes (pg 94):

  seal /class/ => /class/

    seal makes the /class/ read-only and, in addition, new subclasses
    cannot be created from the /class/.

Thus marking a class as sealed *did* prevent one from subclassing. I
should read the latest DRM for a more up to date understanding. ;-)

>In the case of Dylan, a large part of the reason for having "sealing" is 
>to enable more static, faster, code to be generated.  In order to do 
>this, the compiler needs to know about the sealing while it is compiling 
>any code that uses that class.  The greatest effect tends to come while 
>compiling code that is in the same compile unit as the class itself, 
>which means that the sealing has to happen in either the source file 
>containing the class, or else perhaps in the source file which contains 
>the import/export information for that module.

I will concede that separate compilation along with internal
annotations may yield better code optimization than without the
annotations but I am, as of yet, still undecided about the need for
separate compilation [1] and it isn't apparent to me that external
annotations won't achieve the same effect. Not having internal
annotations would allow reuse of the source in more projects than
would be possible with internal annotations due to not prematurely
declaring a class sealed.

[1] There are indications that separate compilation may be unnecessary
with today's machine resources. As one data point, the SmallEiffel
compiler does whole program source compilation in a fraction of the
time of other Eiffel compilers and seems to provide excellent code
optimization. From what I can tell, the speed of compilation is the
result of building an in-core representation of all the source files
before beginning compilation. Since Eiffel is a semantically rich
language, the SmallEiffel compiler may be representative of what could
be done with other languages if the separate compilation model is
abandoned.

BTW, complete source compilation allows the maximum amount of
information to be available so that a compiler can eliminate most of
the unnecessary dynamicism [2]. External annotations, supplied as part
of the nearly ubiquitous "project IDE approach" perhaps, could take
care of the rest without preventing the classes from being reused.

[2] The Concurrent Aggregates (CA) compiler of the Illinois Concert
system <http://www-csag.ucsd.edu/projects/concert.html> used whole
program analysis, concrete type inference, flow analysis, and call
site specific class/methond cloning to obtain performance comparable
to that obtained with C or Fortran from a fully dynamic language
without any annotations! (Actually, there were a few type annotations
for the methods of "primitive types", which were actually defined in
CA rather than assembly or C, but there were none for user defined
types.) The CA compiler was a research tool written in Lisp and was
not particularly fast or efficient. I believe many of the techniques
could be implemented in a production compiler without sacrificing
compilation speed if that was the goal. Alas, the project has been
completed (i.e., the students have all graduated) so I'm not sure we
will ever know for sure if such a compiler can be made faster.

The purpose of the above discussion is to point out that one does not
necessarily to have to separate compilation nor is it necessary to
have internal annotations to achieve good performance. As I believe
both the existing Dylan compilers, Gwydion and FD, assume separate
compilation, the point is moot as far as Dylan is concerned. The same
can be said for Java.

>> My experience with Java has indicated that internal annotations are a
>> problem. By declaring a class final so that it cannot be modified, we
>> are presupposing that the class is complete and needs no modification
>> or extension. Invariably, however, the class is not complete for all
>> uses and yet it cannot extended because it is final. The programmer's
>> only recourse is to duplicate the functionality of the finalized class
>> and then to extend it. 
>
>Dylan avoids this problem to a large extent by allowing subclasses to be 
>declared in the same compile unit with the sealed class.  So it is not 
>that the class has *no* subclasses, but that the list of possible 
>subclasses is fixed and known to the compiler (and in many cases is 
>empty).
>
>Thus Dylan programmers only have this problem when they want to extend 
>someone *else's* sealed class, and in particular, if they want to extend 
>a sealed class declared in the runtime library, such as <integer> or 
><single-float> or <byte-string>.  Of course in Java there is no question 
>of being able to extend "int" or "float" because they aren't classes in 
>the first place.

This is precisely when I have had difficulty with internal
annotations. If the writer of the library (package in Java or module
in the Dylan context) did not forsee a need to extend a class, I am
unable to reuse those bits that will work unchanged and to redefine
those bits that do not. (And sometimes, code that one writes must also
be treated as if someone else wrote it because changing it would
affect other projects which also use the code.) While it is possible
to remove internal annotation from the source and recompile, compilers
that assume internal annotations will now have less information to
perform optimizations. On the other hand, compilers that assume
external annotations can be given those annotations. Thus it appears
to me that external annotations allow better reusability and good
performance.

>> Additionally, having the annotations external to the source
>> naturally leads to allowing specific instances to be sealed while
>> leaving others unsealed.
>
>I'm sorry.  I don't understand your intent.  Do you propose that 
>particular *instances* of some class might be sealed/final, but that 
>other objects of that class will not be?  How would that work?  What 
>would it mean?  As I understand it, sealed/final is an attribute of a 
>class, not of an object.  [bindings can also be final (called "constant" 
>in Dylan), but that's an entirely different thing]

My thinking on this point is still a bit abstract. Thinking back to my
experience with Concurrent Aggregates (see [2]), site specific
optimizations were very important in obtaining "maximum performance".
I was applying the experience out of context to what could be done if
annotations were external. It would be unwise to read more into it
than this.

>In Dylan, at least, sealing is mostly useful because of libraries and 
>separate compilation [1].  If you compile the whole program at once then 
>the compiler can see all the classes and sealing declarations are (in 
>theory) unnecessary because the compiler can automatically seal 
>*everything*.  When you compile a library, however, the compiler has no 
>way of knowing whether users of the library might want to extend classes 
>exported by the library, so a programmer declaration -- visible to the 
>compiler at the time the library is compiled -- is the only choice.
>
>[1] in Dylan it is also possible to create new classes at runtime, by 
>calling make(<class>, ...).  Most programs don't do this, and most 
>programs are written such that the compiler can prove that they don't do 
>it.

As I said earlier, I am not sure whether or not separate compilation
is sufficiently important to fix that dimension and thereby constrain
other choices in the program development search space. Even assuming
the need for separate compilation (in order to ship binary libraries,
for example), that still does not imply that annotations need be
internal. External annnotations would also suffice. (They might be
less convenient, however.)

Mark (who is awaiting your though provoking comments)

-- 
Mark K. Gardner
RADIANT Team
Network Engineering, CIC-5
Los Alamos National Laboratory
P.O. Box 1663, M.S. D451
Los Alamos, NM 87545
Email: mkg@lanl.gov
Phone: 1-505-665-4953
-- 



Follow-Ups: References: