[comp.lang.eiffel] Improved export syntax proposal

rick@tetrauk.UUCP (Rick Jones) (05/29/90)

I would like to add some thoughts to the recent discussion on the syntax of
export declarations in Eiffel.

(I have only just come onto the News, hence the apparent lateness of this
contribution.  I have, however, been doing some fairly intense evaluation of
Eiffel 2.2 over the last 6 months).

The various suggestions are certainly interesting, and I would generally agree
that the language would be more elegant without the export clause.  The main
point in favour of keeping it seems to be the advantage of grouping the names
of all exported features together.

Bob Wiener mentioned the importance of source style in declaring all exported
features together, and thus all secret features together.  How about
formalising this in the syntax?  To me the name "feature" implies export, so I
would suggest something like:

	feature
		count: INTEGER ;

		doit is
		do
		end ;

		-- etc

	secret
		state: BOOLEAN ;

		-- etc
	end

This introduces "secret", already widely used in Eiffel terminology, as a new
keyword.  For restricted exports, another section could be permitted in the
form:

	feature {ONECLASS, OTHERCLASS}

		-- etc

This would overcome another comment regarding the tedium of having to repeat
export restrictions after every affected feature.  (In practice, all or most of
a class's restricted exports will have the same restrictions.)

If you don't want another keyword, "feature" for secret, and "feature export"
(or even "feature {ANY}" - think about it!) could be adopted.


As for inheriting exports, this is certainly an essential facility, but the
implementation of "repeat" in 2.2 is not nice, and gives the impression of
being shoved in rather hastily.  With or without the export clause, it should
definitely be done in the inheritance section, and I would agree with the
suggestion of :-

	inherit
		export A
		-- etc.

		-: as being the cleanest.

I would like to suggest a possibly controversial idea on this theme, though:
when is there any requirement *not* to inherit a parent's exports?  There is no
size or performance overhead in exporting features, so the argument is purely a
philosophical one, and my reasons go thus:

The purpose of having secret features is two-fold

a.	to hide the implementation of a class, so that a client class *cannot*
	be written which is dependent on its supplier's implementation, thus
	allowing implementations to be changed without breaking programs.

b.	to prevent a client using what is in effect a private subroutine of a
	supplier class, whose unrestricted use could break the supplier class
	invariant, etc.

If a class inherits features from its parent, and chooses not to export them,
they do *not* become inaccessible to clients since an object of the child class
can be accessed via a reference of its parent's type (a fundamental concept of
OO languages!).  Features which are redefined in the child are also still
accessible via the parent type due to dynamic binding which (thank goodness)
cannot be prevented in Eiffel.

If this is viewed in terms of the concepts "inheritance of abstraction" versus
"inheritance of implementation", Eiffel *always* implies the former.  The
inheritance of invariants enforces this even further (redefined routines should
also inherit their parent's pre- and post- conditions, but don't - a sore
point).

Therefore, there seems little reason not to inherit exports, or if you have a
reason non-inheritance should be the exception, with inheritance the default.
This leads to my suggestion of:

inherit
	A			-- exports repeated by default
		rename foo as bar
		redefine foo
		export bar	-- exports the renamed feature
		;
	secret B		-- exports not repeated
		export xyz
		;

The export statement in the position shown (suggested by Steve Tynor) covers
two possibilities:

With A, renaming and redefining foo means that the new version of foo is the
effective final version for this class, with bar being the parent version of
foo.  Assuming foo is exported by A, the export inheritance means that the name
exported here is foo, not bar (without the redefine it would be bar).  If bar
(i.e. the parent version of foo) also needs to be exported from the child, this
must be explicitly stated, and there is nowhere else to do it if we remove the
main export clause.

With B, we have inhibited automatic export of B's exported features, but we do
want to export xyz, so we have to say so.  It also allows the child to export
one of the parent's features which the parent didn't export, though I think
that wanting to do this implies suspect design somewhere.

One can take an even more purist line and say that features that the parent
didn't export were designed as internal only, and so the child should have no
right to export them at all.  This includes the inherited foo renamed as bar in
the example above, since the redefined foo is the implementation for the child,
access to the parent version is an internal convenience for the child class.

Secret inheritance may be regarded as superfluous, and if this view is also
taken, there is no need for export as even a sub-section of inherit, since all
exporting is controlled by the section in which the feature was originally
defined.  It certainly simplifies the language, though going this far could
be guaranteed to break many existing working programs;  the compiler would need
a compatibility mode as an option (uugh!).

The BIG problem in doing this is how to cater for classes which are designed
for inheritance, not as suppliers (like the library classes BASIC, MEMORY,
EXCEPTIONS, etc).  They are written with their features exported, because if
they aren't "short" doesn't document them!  A class inheriting from one of
these almost certainly does *not* want to export these features to its clients.
Perhaps the cleanest solution would be to have another section in addition to
"feature" and "secret" in which to place features of this sort.  They would not
be exported, but would be identified by "short" as requiring description, and
in slightly different terms from exported features.  This would also be a good
way to define tricky things like deferred secret functions called from routines
in a parent class but resolved only in descendants (like a "match" function
where the searching loop is in the parent).

I seem to be re-writing the language ... !
But could this stimulate some interesting discussion?


I also have some comments on John Potter's query about restricted exports,
but this article's long enough already.  Watch this space ...

-- 
Rick Jones					You gotta stand for something
Tetra Ltd.  Maidenhead, Berks			Or you'll fall for anything
rick@tetrauk.uucp (...!ukc!tetrauk.uucp!rick)	     - John Cougar Mellencamp