[comp.lang.eiffel] Eiffel vs. C++

dmg@ssc-vax.UUCP (David Geary) (06/01/89)

  I've been programming in C for about 5 years, and
just recently started using C++.  I would like to
start a discussion of Eiffel vs. C++.  I understand
that both languages use C as a base language, and
that both implement OOP features, and it seems as
though the two have much more in common, aside from
syntactic differences, than they have differences.

  Note that I'd like the discussion to center around
version 2.0 of C++ vs. the most current version of
Eiffel.

  I am aware of the fact that Eiffel has a robust
library of base classes, but I would like to see
a discussion of language *features*.

  About the only difference that I can discern is the
fact that Bertrand Meyer posts more often to comp.lang
.eiffel than Bjarne Stroustrup posts to comp.lang.c++
;-) ;-)
  
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace, Seattle                 ~ 
~ "I wish I lived where it *only* rains 364 days a year" ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

sarkela@eiffel.UUCP (John Sarkela) (06/03/89)

>  I've been programming in C for about 5 years, and
>just recently started using C++.  I would like to
>start a discussion of Eiffel vs. C++.  I understand
>that both languages use C as a base language, and
>that both implement OOP features, and it seems as
>though the two have much more in common, aside from
>syntactic differences, than they have differences.

First, consider the relative grammatical complexity of the
languages.  Eiffel is an LL(1) language, whereas net
comments seem to suggest that C++ may not even be LALR(1).
Much of the grammatical complexity of C++ seems to derive
from its historical precedents.  The simplicity of the 
Eiffel grammar has much to do with the fact that it does
not attempt to be source compatible with prior languages.
Eiffel, the language, is not C based. The relation which 
Eiffel shares with C is solely that of source language 
to target language.

Second, consider some the features of C++ which Eiffel does 
not possess.  Eiffel does not possess global variables.
Eiffel does not possess pointers. The elimination of 
gratuitous pointer aliasing and extern'ed globals allows a 
smart compiler greater lattitude in generating optimized code.  

Third, consider features of Eiffel which C++ does not possess.
One of the stronger motivations for using object oriented
techniques, is to take advantage of sharing at least specifications
and hopefully implementations.  With untyped object languages such
as Smalltalk this follows naturally.  In the case of statically
typed languages, however, the denotations for collection,
aggregate, or container classes must either be duplicated for
each contained type or or the container must be parameterized
by the contained type.  The Eiffel generic class parameter
language construct directly addresses this issue.  While
ad hoc mechanisms may be used to rewrite nearly duplicate
class declarations in a language which does not support
genericity, IMHO it is perhaps better to put all type
parameterizations within the scope of the language type system. 

Eiffel has included for some time multiple inheritance.  At 
this point in time, I do not have access to a description
of MI in C++.  Given a familiarity with C, however, I expect
that namespace traditions of C could make MI a subtle 
feature of C++ Rev. 2.0.

Finally, consider one of my favorite uses of MI in Eiffel, the
specification class. Given the ability to specify class invariants,
and method pre and post conditions, one can write a specification
class which fully qualifies the domains and ranges of all class
methods. Eiffel provides language hooks which allow straight forward 
specification of these qualities independent of the implementation 
of the components.  One thus may use multiple inheritance to provide 
both a "is-a" categorization of the refined class as well as the 
"code reuse" of implementation inheritance.  I don't have C++
2.0 documentation so I don't know the extent of exception support,
nor do I know the rules for MI in C++, can anyone give a definitive
explanation?  

BTW, can anyone clear up exactly how one specifies the input restrictions
and legitimate outputs of library C++ components?

Conclusion: Eiffel is a grammatically simpler language than C++.
Eiffel does not have many language features that C++ inherited from C.
Eiffel has language support for component specification and qualification.


John Sarkela		sarkela@eiffel.com

UH2@PSUVM.BITNET (Lee Sailer) (06/04/89)

While I agree with most of this comment, I want to clear up
one possible small understanding.

In article <148@eiffel.UUCP>, sarkela@eiffel.UUCP (John Sarkela) says:
>
>Eiffel does not possess pointers. The elimination of

Lest programmers get the wrong idea, let me say that Eiffel DOES have
a mechanism that allows things to point at one another.  In C (and C++,
I guess) a pointer might be better called an "address".  C is famous for
offering the programmers access to low level machine primitives
such as memory addresses, as you all know.  The probelm is that the
compiler cannot possibly know what the programmer intends to do with
the address, and thus cannot optimize well.  The same argument has
been made about strings---C does NOT have a string type.  We fake it
with pointers (addresses) and arrays (pointers 8-).  In a language
that does have a specific string data type, the compiler writer has
a chance to do some optimization tricks otherwise not available.
>gratuitous pointer aliasing and extern'ed globals allows a
>smart compiler greater lattitude in generating optimized code.
>
>Third, consider features of Eiffel which C++ does not possess.
>One of the stronger motivations for using object oriented
>techniques, is to take advantage of sharing at least specifications
>and hopefully implementations.  With untyped object languages such
>as Smalltalk this follows naturally.  In the case of statically
>typed languages, however, the denotations for collection,
>aggregate, or container classes must either be duplicated for
>each contained type or or the container must be parameterized
>by the contained type.  The Eiffel generic class parameter
>language construct directly addresses this issue.  While
>ad hoc mechanisms may be used to rewrite nearly duplicate
>class declarations in a language which does not support
>genericity, IMHO it is perhaps better to put all type
>parameterizations within the scope of the language type system.
>
>Eiffel has included for some time multiple inheritance.  At
>this point in time, I do not have access to a description
>of MI in C++.  Given a familiarity with C, however, I expect
>that namespace traditions of C could make MI a subtle
>feature of C++ Rev. 2.0.
>
>Finally, consider one of my favorite uses of MI in Eiffel, the
>specification class. Given the ability to specify class invariants,
>and method pre and post conditions, one can write a specification
>class which fully qualifies the domains and ranges of all class
>methods. Eiffel provides language hooks which allow straight forward
>specification of these qualities independent of the implementation
>of the components.  One thus may use multiple inheritance to provide
>both a "is-a" categorization of the refined class as well as the
>"code reuse" of implementation inheritance.  I don't have C++
>2.0 documentation so I don't know the extent of exception support,
>nor do I know the rules for MI in C++, can anyone give a definitive
>explanation?
>
>BTW, can anyone clear up exactly how one specifies the input restrictions
>and legitimate outputs of library C++ components?
>
>Conclusion: Eiffel is a grammatically simpler language than C++.
>Eiffel does not have many language features that C++ inherited from C.
>Eiffel has language support for component specification and qualification.
>
>
>John Sarkela            sarkela@eiffel.com

sarima@gryphon.COM (Stan Friesen) (06/04/89)

In article <2689@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>
>  I've been programming in C for about 5 years, and
>just recently started using C++.  I would like to
>start a discussion of Eiffel vs. C++.  I understand
>that both languages use C as a base language, and
>that both implement OOP features, and it seems as
>though the two have much more in common, aside from
>syntactic differences, than they have differences.
>
>...
	I may as well put in my two cents worth.  My impression is that
Eiffel is a "higher level" language than C++.  That is Eiffel is a very
strongly typed OOP language, with a very simple, limited implementation
of objects, whilc C++ is a very flexible language that allows you to
get into the guts of the system when you need to.  Thus, as someone else
stated, Eiffel feels like Pascal and C++ feels like C.
	Eiffel is very simple syntactically, at the cost of requiring
you to do everything its way.  In particular, except for the basic scalar
types, *everything* is a class.  There are no seperate derived types,
such as pointers and arrays.  A class instance is essentially always a
pointer, but without the ability to do pointer arithmetic, or in fact
anything except allocate, deallocate, and dereference.  Thus it acts like
a dynamically allocated instance of an object. (In fact this is what Meyer
would call it, rather than a pointer).   Because of this there are a
number of things not possible in the language.  For instance the standard
library class ARRAY, used to make array objects via inheritence, had to
be implemented in C and grafted into the language using the "foreign"
language import capability.  This limitation is not often important, since
most of the common cases where going outside of Eiffel have been anticipated
and included in the standard library.
	C++, on the other hand, is more complex because it allows you to
decide how you want to implement something.  It has built in all of the
scalar and derived types from C, thus allowing direct manipulation of
low-level implementation details when necessary.  It still has all of the
class features that facilitate OOP.  It has dynamic allocation, when needed,
and it allows run-time typing (using virtual functions).  But if you don't
need them you don't have to take them.
	Thus the trade-off is a simpler, easier to understand language
versus one that gives you more control.
>
>  About the only difference that I can discern is the
>fact that Bertrand Meyer posts more often to comp.lang
>.eiffel than Bjarne Stroustrup posts to comp.lang.c++
>;-) ;-)
>  
	Well, Bjarne Stroustrup used to post here occasionally, but he
claims to be too busy now.  So Andrew Koenig has taken over posting here
for him.
-- 
Sarima Cardolandion			sarima@gryphon.CTS.COM
aka Stanley Friesen			rutgers!marque!gryphon!sarima
					Sherman Oaks, CA

bertrand@eiffel.UUCP (Bertrand Meyer) (06/05/89)

From article <2689@ssc-vax.UUCP> by dmg@ssc-vax.UUCP (David Geary):

> I would like to start a discussion of Eiffel vs. C++. [...]
> About the only difference that I can discern is
> [joke about compared newsgroup patterns].

    Since we often get the question of Eiffel versus C++, Mr. Geary's
initiative provides a welcome opportunity to clarify what I see as the
major differences. I am the main designer of Eiffel, so the following
discussion cannot claim to be that of an independent observer, although it
is certainly honest, and technically correct to the best of my knowledge.
In all likelihood, others will contribute different viewpoints.

    I certainly cannot claim to be a C++ expert. If I misrepresent
C++ in any way, it will be by mistake, not design. Should this occur,
someone will certainly correct the mistake, either by writing to me (in
which case I will post the correction if it does turn out that I have
written something wrong) or by posting directly.

    This response has three sections: general observations; technical
differences; conceptual differences. I apologize for its length; there is
really a lot to say. Also, there is little new in the material below,
much of which may be found in previous publications about Eiffel; none of
my previous publications, however, has studied Eiffel from the point of
view of a comparison with C++.

    Although I believe that the Eiffel environment and tools and the
standard Eiffel libraries provide some of the major arguments for Eiffel,
I will (with two exceptions explained below) limit the discussion to
the languages proper, so as to abide by Mr. Geary's request: 

> I am aware of the fact that Eiffel has a robust
> library of base classes, but I would like to see
> a discussion of language *features*



1 - GENERAL OBSERVATIONS
------------------------

    Eiffel was designed in 1985, initially not as a language for the rest
of the world, but as an internal tool for a development that Interactive
Software Engineering started at that time. We would have preferred to use
an existing language and environment, but an examination of possibilities,
including C++, quickly showed that nothing was even close to
the minimum required for developing software according to the modern
principles that I (then still a professor at the University of California,
Santa Barbara) was teaching to my students. I did not want to develop a
split personality or to fall into the ``do as I say, not as I do''
syndrome.

    I am mentioning this because in a way we had an unfair advantage:
when we started, C++ existed. Although we certainly did not imitate C++,
its very existence was helpful because it showed clearly what
we did *not* want Eiffel to be. In a similar vein, we also looked at Ada,
although in this case the ratio of positive to negative influences
was higher. Even though Ada is not an object-oriented language, its
syntax conventions and its handling of elementary constructs
(expressions, control structures etc.) definitely influenced the
corresponding Eiffel constructs. (By the way, only three languages
did exert a strong semantic influence on Eiffel. One was Simula 67; the
other two were not programming languages but specification languages:
Abrial's Z, in whose design I was somewhat involved around 1978-79,
and my own M, a successor to Z and to this day an unfinished design.
A less important influence was Alphard.)

    Finally I do not think that in the long term Eiffel is really
``competing'' with C++. They have almost nothing in common in their aim
and spirit, as explained in the final section of this message.
In my undoubtedly biased view, the real competitor to Eiffel is Ada.
(``Competitor'' for me is a positive word. When you acknowledge
a design as a competitor to yours, it implies respect.)
Ada, as already mentioned, is not truly object-oriented, but its official
charter (reliability, reusability, professional high-quality software
development etc.) is very similar, on paper at least, to that of Eiffel.


2 - TECHNICAL DIFFERENCES
-------------------------

Software structure

    Eiffel software is organized in autonomous software units
(classes), meant to be compiled separately. There is no main program.
This is what I believe should be the case in object-oriented
programming. In contrast, I understand that C++ still follows
the traditional C model. Quoting from Dr. Bjarne Stroustrup's ``The
C++ Programming Language'' (Addison-Wesley, 1986), which seems to be the
major reference on C++, page 22, lines 13-14: ``A C++ program typically
consists of many source files, each containing a sequence of declarations
of types, functions, variables, and constants''. This is very far from the
object-oriented model of software decomposition. Furthermore, reports from
actual users of C++ seem to indicate a heavy use of ``include files'', a
technique which I don't fully understand in the C++ context, and which
has no equivalent in Eiffel.


Assertions

    A fundamental property of Eiffel software is that it may be equipped
with assertions. Assertions are elements of formal specification that
serve to characterize the semantics of classes and their routines
independently of their implementation.
Assertions include in particular routine preconditions (which must be
satisfied when a routine is called), routine postconditions (ensured by
the routine on exit) and class invariants (global consistency conditions
applying to every instance of a class).

    Assertions are essential for documenting components.
As a matter of fact, I do not understand how one
can talk about the very idea of reusable software components without
assertions. Using a hardware analogy, a software component without
assertions is similar to, say, an amplifier without precondition
(the acceptable input voltage), postcondition (the gain,
expressed as acceptable ratio of output to input) and invariant
(including for example the temperature limits expected and
maintained by the amplifier). Yet of widely available programming
languages, only Eiffel has these notions.
(A system that does have assertions, and in fact ones that are more
sophisticated than Eiffel's current ones, is David Luckham's Anna system,
developed at Stanford on top of Ada. As far as I know, however, this is
not a deliverable product.)

    Beyond their documentation uses, assertions, which optionally
may be monitored at run-time, provide a remarkable debugging and
testing aid. At the recent International Eiffel conference in Paris,
one user organization (Cognos Inc.) reported that
they no longer perform traditional unit testing, having
replaced it by assertion monitoring.


Exceptions

    Eiffel has exception handling. Its exception mechanism is original and
I believe it is one of our major contributions, based on the theory of
``Programming by Contract''. As far as I know, there is
no exception mechanism in C++. I believe that one cannot write
serious software without having a way to recover cleanly from unexpected
cases.


Global variables

    Consistent with the absence of main program is the absence of
global variables. Global variables are well known to be detrimental to
modularity and more generally to quality. The Eiffel technique
of ``once routines'' is used to ensure disciplined sharing
between classes when needed. (See my column in the Journal of
Object-Oriented Programming, vol. 1, no. 3, pages 73-77,
``Bidding Farewell to Globals''.)

    In contrast, C++ seems to support global variables in the C style.


Genericity

    Eiffel classes may be generic, i.e. parameterized by types,
as in LIST [T]. Here actual uses of the class may use any type (class)
as actual generic parameter, as in

    my_list: LIST [TEXT_LINE]

    The genericity may be constrained, as in MATRIX [T -> NUMERIC], which
specifies that actual generic parameters must be descendants, in the sense
of inheritance, of class NUMERIC (equipped with the operations "+", "-",
"*" etc.). Descendants of NUMERIC include (in version 2.2) predefined
types such as INTEGER and REAL. The operations of NUMERIC are available,
within the class, on any variable of type T - so that it can define,
for example, routines for adding and multiplying matrices.
Note that in this example MATRIX itself might inherit from NUMERIC.

    Nothing of the sort exists in C++. This means that generic structures
must be simulated by forcing type conversions, or ``casts'', using
low-level C techniques. This defeats any attempt at static typing.

    A paper was published not long ago about a proposal for class
parameterization in C++. (Although the paper was published in a refereed
journal, it regrettably did not mention any of the
two object-oriented languages that offer such a facility: Eiffel and
Trellis-Owl, the latter designed by Craig Schaffert and others from DEC).
Since by all reliable accounts the inclusion of such a facility in any
form accessible to C++ users is several years away, it cannot be
considered in any serious discussion. On that kind of time scale one can
promise anything.


Dynamic binding

    Dynamic binding is the default mechanism for routine calls in Eiffel
(achieved without any undue effect on performance). The default
policy in C++ is static binding; dynamic binding is only applied to
routines declared as ``virtual''. This may look like an acceptable
requirement to impose on programmers but I believe it is not.
The whole idea of inheritance is that you may reuse a class
later on by writing a descendant and adapting it to new uses
by overriding some of the routines of the original -
within the original semantic constraints, as defined by assertions.
This should be done without impacting the original, which may be
used by many other ``client'' classes. (These concepts are explained
in my book ``Object-Oriented Software Construction, Prentice-Hall, 1988,
as the ``Open-Closed Principle'', section 2.3.) In such a case
the designer of the original routine may have had no inkling whatsoever
that the routine would ever be redefined and subjected
to dynamic binding. This is incompatible with the requirement
that the original designer should have declared the routine
as virtual in the first place. 

    Instead of forcing the programmer to take care of low-level
optimizations, the Eiffel approach makes the compiler responsible
for exploiting the performance of static over dynamic binding.
The optimizer, working on a set of classes, generates code that applies
static binding to any routine which warrants it (because it is
never redefined).

    Performing tedious and potentially dangerous optimizations
in a safe way should be the role of computers, not humans. 


In-line expansion

    In C++ as in Ada a routine may be declared as ``in-line'', meaning
that calls will be expanded in-line to gain performance. No such mechanism
is available in Eiffel. Contrary to what one might think at first sight, I
believe this to be a serious advantage for Eiffel. As soon as a routine is
declared as in-line, its usefulness is severely limited because it no
longer is a normal routine that can be redefined and
subjected to dynamic binding. The discussion of the previous paragraph
applies even more strongly.

    In Eiffel, once again, the corresponding optimizations are performed
by the compiler, not by the human user. The optimizer will automatically
expand certain routines in-line based on systematic criteria beyond
programmer control. One of the criteria is of course that the routine not
be subject to redefinition and dynamic binding; the number of calls in the
code is another.

    Again, this seems the safe and efficient approach. Computers can
perform this kind of task both more efficiently and more safely than
humans.


Operator overloading

    The term ``operator overloading'' is not entirely adequate since the
issue is whether functions may be assigned names that will be used in
prefix or infix form in calling expressions. This is a syntactic, not
a semantic issue; the more important form of overloading, the semantic one,
is provided in the object-oriented context by redefinition and dynamic
binding.

    C++ offers the possibility of using an operator
(from a set of predefined ones) as function name; a similar possibility
is offered in Eiffel 2.2, although it was not present in earlier releases.
So the two languages are indeed comparable in this respect.


Consistency of the type system

    Beginning with version 2.2, Eiffel has a fully consistent type system in
which every type, including basic types such as INTEGER, REAL and so on,
is defined by a class (using the multiple inheritance mechanism). This was
made possible by the introduction of the notion of expanded class, of
special BITS M classes (whose instances are bit strings of length M),
and of infix/prefix operators as discussed above. This is achieved without
any effect on the efficiency of dealing with simple values such as
integers, characters and the like. The advantage is mainly a conceptual
one - being able to work with a single set of concepts admitting few
special cases.

    There doesn't seem to be anything similar in C++, which uses the C
types as basis.


Type checking

    Because of the absence of genericity and the presence of the full C
type system with its casts and other unsafe mechanisms, C++ cannot be
reasonably be called a statically typed language. In contrast, Eiffel was
designed as fully typed.

    The present Eiffel compiler misses a small number of type violations
(arising in particular from cases in which polymorphism enables a client
to evade an export or redefinition constraint). These cases seldom arise
in practice, which is not an excuse for not handling them properly. Even
with the current implementation, however, Eiffel is incomparably
more type-safe than C++ because of the presence of genericity,
of the strict enforcement of type checks in assignments,
and of the absence of any unsafe casts or conversions.


Friend functions

    C++ has a notion of friend function which, as I understand it, makes
it possible to define routines outside of the object-oriented framework.
There is nothing equivalent in Eiffel. This facility is not missed;
I would see its introduction as a dangerous violation of the object-oriented
principles.


Deferred classes

    An extremely important notion in Eiffel is that of deferred class,
which describes a non-fully-implemented abstraction. Deferred classes
are used to capture commonalities and are central to the object-oriented
approach. Two aspects are particularly important: the ability to define a
partially deferred class, which contains both implemented and
non-implemented routines; and the ability to attach assertions to a
deferred class and its deferred routines, and thus to specify
the behavior of yet to be implemented software.

    C++ as described in published references does not appear to support a
similar notion. I have heard, however, that the forthcoming version of
C++ has a notion of abstract class, which is meant to play the same role.
Perhaps someone will describe this facility in detail so that readers
can judge.


Multiple inheritance

    Multiple inheritance is fundamental in the Eiffel approach. We made
every effort to handle it in a very clean way; name clashes, in particular,
are treated in what I believe is the right way. (More precisely, I do not
know of any satisfactory solution in any other language. This is a strong
statement, and proponents of other languages are welcome to respond to the
challenge.)

    The published references on C++ systems exclude multiple inheritance
which, however, is rumored to be imminent. I must confess
this is one aspect on which we, at Interactive Software Engineering, are
rather touchy. The first time I personally heard about the ``imminence''
of multiple inheritance in C++ was November of 1986. Since then, that is
to say for two years and a half, we have essentially been unable
to use the presence of multiple inheritance as an
argument for Eiffel - so successful have others been in persuading almost
everyone that multiple inheritance in C++ was around the corner. Here I
would like to appeal to developers of software tools and
suggest a universal ethical rule: whenever you refer to a feature that is
not yet available in the released distribution of your product, mention it
unambiguously in every relevant publication, together with
an estimated date of availability (to the public, not internally).
The name for such a policy is simple: honesty.

    This being said, it is indeed possible that multiple inheritance
will become available in C++ during my lifetime. It is not clear
from what I have read and heard that the non-trivial problems of
multiple inheritance, such as name clashes, have been properly addressed.
(If I am wrong on this, please enlighten me.) 


Renaming

    Eiffel offers a powerful technique in connection with inheritance:
renaming. A class can rename inherited routines and attributes
(i.e. methods and attribute variables for those who prefer such terms).
This is used for removing name clashes in multiple inheritance and also,
perhaps even more importantly, to provide locally adapted terminology
when you inherit the right features but under the wrong names. As
discussed in my OOSC book referenced above (section 10.4.7) and in a JOOP
column (Vol. 1, no. 4, pages 48-53), this is essential if inheritance is
to provide support for reusability in a practical industrial context.


Garbage collection

    This item and the next violate Mr. Geary's request to limit the
discussion to language features. I have included them anyhow because,
even though they are environment rather than language features,
they are made possible or next-to-impossible by the language design.
    
    To write serious object-oriented software, which at run time will
inevitably generate many objects, some of which may become useless,
one needs a good garbage collector. This is the case in Eiffel
(which uses an incremental, parallel scheme so as not to impair performance).
As far as I know, C++ systems do not support garbage collection,
which would be extremely difficult if not impossible to implement
because of the presence of C types and mechanisms.


Automatic recompilation

    One of the most important practical aspects of Eiffel is the automatic
compilation mechanism, based on automatic analysis of inter-class
dependencies (multiple inheritance and client). This removes the need for
make files and include files. Although I recall some seemingly interminable
notes on the feasibility (or lack thereof) of a similar mechanism in
comp.lang.c++, I don't know of any implemented mechanism for C++.

    Again, this seems due to the very design of the language; and again,
the difference seems to result from irreconcilable views of what should be
done by computers and what should be the province of humans. The Eiffel view is
that error-prone and tedious management tasks should be handled by tools,
and that programmers should concentrate on solving programming problems. 


Pointer arithmetic etc.

    One of my major objections to C++ stems from what that language has
rather than what it has not. Because C++ retains almost total
compatibility with C, it keeps all its low-level and dangerous features.
The design of C dates back to the late sixties and is obsolete
by modern software engineering standards.
Compatibility with C means that in C++ you still have pointers,
type casts, pointer arithmetic, function pointers, malloc, free, bizarre
operator precedence (the famous asterisk/parenthesis bugs),
weak type checking and so on.

    I strongly disagree with this approach if the goal is to obtain software
quality. Take pointer arithmetic, for example. I would contend that you can
have quality software, or you can have pointer arithmetic; but you cannot
have both.

    In Eiffel, the choice has been made. None of these low-level features
are present (as John Sarkela pointed out in a previous message); needless
to say, they are not missed.


Compatibility with C software

    C++ is obviously very compatible with C. But in Eiffel too you can
easily communicate with C software; both call-in and call-out are
provided. This makes it possible to reuse existing software easily.
The need for such communication was not, however, deemed to be a good
argument for impairing the consistency of the language itself.


Simplicity and ease of learning

    Much of the plea for C++ is based on the observation that it provides
an easy transition from C, which (for better or worse) is the language
many programmers know nowadays. Using Dr. Brad Cox's expression (meant
for Objective-C), this supports an ``evolutionary'' approach.

    I can certainly respect this view and its appeal to software managers
in industry. But I believe that by considering it more closely one will
find it short-sighted and ill-founded.

    Learning a new language such as Eiffel is nothing for a
competent programmer. For Eiffel, which is small and simple,
the learning process typically lasts a few days at most.
Nobody has ever told us that Eiffel was difficult to learn.
(If you read this, have tried to learn Eiffel,
and found otherwise, please respond!) I believe that the process of
going to Eiffel is in fact much smoother, as you don't have to use
a confusing mix of old and new concepts.
In a language that you master totally, you feel
confident and you can concentrate on your job rather than on
the language intricacies.

    Also, the brief initial shock produced by the realization that you
cannot easily write your programs in a traditional way any more is,
in the experience reported by Eiffel users, highly salutary.


3 - CONCEPTUAL DIFFERENCES
--------------------------
    
    The considerable differences listed above more than offset, in my mind,
any similarity that may seem to exist between Eiffel and C++.
Beyond these individual technical differences, the contrast between
the two languages is deep and conceptual. Eiffel is a new
language and environment designed with a precise charter
(enabling the production of very high quality software by professional
programmers). C++, as I see it, is an attempt at a more modern version of C.
(The basic C++ reference quoted above, in its ``historical note'' on page 5,
writes that ``the difference between C and C++ is primarily in
the degree of emphasis on types and structures'') .

    There are undoubtedly arguments for both approaches. Needless to say,
I find the arguments for the first to be stronger.


--------------------


    This is probably overkill already and I shall resist the temptation to
go on. Have I at least succeeded in convincing Mr. Geary that the technical
differences are deep ones?

    In all likelihood, this note, prompted by Mr. Geary's question,
will eventually be rewritten as a short article, so that comments and
criticism will be greatly appreciated. 

-- Bertrand Meyer
bertrand@eiffel.com

lam@tridom.uucp (Larry Morris) (06/06/89)

In article <150@eiffel.UUCP>, bertrand@eiffel.UUCP (Bertrand Meyer) writes:
> 
>     Finally I do not think that in the long term Eiffel is really
> ``competing'' with C++. They have almost nothing in common in their aim
> and spirit, as explained in the final section of this message.
> In my undoubtedly biased view, the real competitor to Eiffel is Ada.
> (``Competitor'' for me is a positive word. When you acknowledge
> a design as a competitor to yours, it implies respect.)
> Ada, as already mentioned, is not truly object-oriented, but its official
> charter (reliability, reusability, professional high-quality software
> development etc.) is very similar, on paper at least, to that of Eiffel.
> 
I find this view surprising, even though I'm willing to concede that Eiffel
is radically different from C++, and more modern in its design.  Ada, from
what I've seen, is used more by mandate than choice [not that it's a 
particularly "bad" language, but I'd be willing to bet that nearly all 
new engineering users of Ada have a DoD standard on their desks].
Setting up Ada as the "competition" seems like a strawman to me.
As for the "charter" of C++, was it intended for unreliable, one-time,
amateur, poor-quality software development?  I doubt that Stroustrup's
intent was significantly different than yours. I see C++, Objective-C and 
Smalltalk as Eiffel's most obvious competitors for the engineering
marketplace, as much for political as design considerations. Ada is likely
to remain comfortably entrenched in its own well-protected market.

> can talk about the very idea of reusable software components without
> assertions...
> maintained by the amplifier). Yet of widely available programming
> languages, only Eiffel has these notions.
Assertion checkers, of course, have been used for years as tools outside
the scope of the language, as libraries, or extracted by tools from
code comments. Placing assertions within classes as part of the language
is, I must agree, a very powerful feature. But Eiffel's design philosophy
calls on programmers to define their classes with assertions in addition
to coding their implementation; something most programmers aren't used to
doing and may view as an onerous task. Since assertion checking isn't any
better than the assertions dreamed up by the programmer, I'm skeptical of
using it to "replace" unit testing.
> 
>     Eiffel has exception handling. Its exception mechanism is original and
> I believe it is one of our major contributions, based on the theory of
> ``Programming by Contract''. As far as I know, there is
> no exception mechanism in C++. I believe that one cannot write
> serious software without having a way to recover cleanly from unexpected
> cases.
> 
I agree 100% with this, and I view it as the single biggest selling point
of Eiffel over C++.
> 
>     In C++ as in Ada a routine may be declared as ``in-line'', meaning
> that calls will be expanded in-line to gain performance. No such mechanism
> is available in Eiffel....
>  The optimizer will automatically
> expand certain routines in-line based on systematic criteria beyond
> programmer control...
> 
I'm a bit skeptical about this approach. In data communications software
(or other types of real-time software) it's frequently necessary to optimize
certain methods heavily. I'd like some choice over this without having to
resort to an assembly language or C call-out. How many times must I reference
the method before your optimizer decides to inline it? How many lines may I
add to the method before your approach changes? By adding a line, will I
speed things up or slow them down?
>     
>     To write serious object-oriented software, which at run time will
> inevitably generate many objects, some of which may become useless,
> one needs a good garbage collector. This is the case in Eiffel
> (which uses an incremental, parallel scheme so as not to impair performance).
> As far as I know, C++ systems do not support garbage collection,
> which would be extremely difficult if not impossible to implement
> because of the presence of C types and mechanisms.
Obviously, one does not need a good garbage collector if one cleans up 
after oneself. Having been burned before by garbage collection, I remain
wary of claims of efficiency. With C++, I control allocation and deallocation
of memory resources explicitly, so I know their performance impact. With
Eiffel, do I just trust that you won't collect garbage at an inopportune
time, like halfway through emitting a frame?

> Compatibility with C means that in C++ you still have pointers,
> type casts, pointer arithmetic, function pointers, malloc, free, bizarre
> operator precedence (the famous asterisk/parenthesis bugs),
> weak type checking and so on.
>     In Eiffel, the choice has been made. None of these low-level features
> are present (as John Sarkela pointed out in a previous message); needless
> to say, they are not missed.
In analyzing incoming data frames, we freqently encounter the problem of
extracting or adding variable-length headers, at various positions in a
byte array. It's most convenient (and efficient) to be able to adjust a byte
pointer, then reinterpret the pointer as a struct pointer. This may not be
"textbook" programming style, but life isn't filled with textbook problems 
either. The pragmatism of C in these situations is one reason I prefer it to
Pascal these days, and why I endure all of C's warts.  Yes, I want many of 
the benefits of Eiffel...but when I need just to get the job done, will I
be calling my old C routines because your choices didn't fit?
>     Learning a new language such as Eiffel is nothing for a
> competent programmer. For Eiffel, which is small and simple,
> the learning process typically lasts a few days at most.
Natch! I learned C in a few days, few being a relative term. Becoming fully
versed and competent took a "few" more, and I might still have a couple days
to go.
You're probably right about being easier to learn than C++, though, not
having the forward interference from C to contend with.

As someone involved in the selection of an OOP language, I have to say that
the decision between C++ and Eiffel isn't a trivial one. Many of the factors
are political, since C++ has a large and "grass-roots" support base, while
Eiffel is relatively new to the scene, and more academic in its "feel." I
think the decision will be influenced strongly by support tools, since
successful OOP programming, IMHO, depends on making classes available to
a team in an accessible and controllable manner. Eiffel has a solid, but
largely proprietary, environment set; C++ seems bogged down in this area,
but with many vendors interested.
I hope both ISE and AT&T feel some healthy competition between their products,
since this will encourage more tool development. These days a language can't
be considered realistically outside of its tool environment; this goes double
for an OOP language.

Larry Morris, Tridom Corporation
...!emory!tridom!lam

aro@aber-cs.UUCP (Andrew Ormsby) (06/06/89)

In article <2689@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>  I've been programming in C for about 5 years, and
>just recently started using C++.  I would like to
>start a discussion of Eiffel vs. C++.  I understand
>that both languages use C as a base language, and
>that both implement OOP features, and it seems as
>though the two have much more in common, aside from
>syntactic differences, than they have differences.

It is true that current implementations of Eiffel use C as a base
language. With Eiffel, however, the use of C is really as a portable
assembler that the Eiffel translator can compile into. This has
presumably greatly reduced the development costs of the compiler for
Interactive Software Engineering, Meyer's firm. There is the added
advantage that it enables them to make use of the machine dependent
optimisers that are usually part of the C compilation systems on
various machines. However, I would contend that the fact that Eiffel
uses C as a "base language" is only an implementation detail.

C++ is very different. To quote Stroustrup in the introduction to the
C++ book, "Except for minor details, C++ is a superset of the C
programming language". C++, quite deliberately, therefore ends up
looking very much like C.

While most current C++ translators are implemented as preprocessors
for C compilers, there are a growing number of true C++ compilers.

My view is that C++ is what people should be using as an alternative
for C in applications where C was really necessary; where there are
programmers around who know how to use it properly. My worry is that
C++'s additional complexity over and above C will make it even more
likely that bad C++ programs are written.  Eiffel may be more
appropriate as a general purpose language; my personal opinion is that
it looks likely to be less easily misused. However, C++ is widely
available and cheap. Eiffel is less widely available and rather
expensive. Its a shame.

>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>~ David Geary, Boeing Aerospace, Seattle                 ~ 
>~ "I wish I lived where it *only* rains 364 days a year" ~
>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Andy Ormsby,				aro@cs.aber.ac.uk
Department of Computer Science,		aro%cs.aber.ac.uk@nsf-relay.ac.uk
University College of Wales,		aro%cs.aber.ac.uk@ukacrl.bitnet
Aberystwyth, Dyfed, UK, SY23 3BZ.	

mgardi@watdcsu.waterloo.edu (M.Gardi - ICR) (06/06/89)

I have heard that eiffel creates hideously large executables from very
trivial programs. Does anyone have any information as to whether this is 
true or not?? I found that using advantage C++ also produced large
executables...one of the reason why I am using Zortech C_++ currently. It does
not seem to have this problem (executable size seems on average to be about
1/5 the size of advantage c++ code).
We're talking 35K here for a hello world program in advantage...something
that can't be tolerated on the PC. One source gave the comparable eiffel     
program a number even much higher.



Peter DeVries
Mutual Life of Canada (519) 888-2957
c/o mgardi@watdcsu

jwg1@bunny.gte.com (James W. Gish) (06/06/89)

In article <150@eiffel.UUCP> Bertrand Meyer writes:

>    C++ is obviously very compatible with C. But in Eiffel too you can
>easily communicate with C software; both call-in and call-out are
>provided. This makes it possible to reuse existing software easily.
>The need for such communication was not, however, deemed to be a good
>argument for impairing the consistency of the language itself.
>

I believe this should be qualified somewhat.  You indeed can make
calls to C routines from Eiffel and vice versa.  But life is rarely
that simple.  You have to map Eiffel objects to C structures and vice
versa.  This is tedious but can be done in some/most(?) cases. One of
the biggest problems that keeps calls from Eiffel to C non-trivial is
the inability to use C include files within Eiffel for the definition
of types on the Eiffel side.  This is a serious obstacle to making use
of much C code.  A case in point is the use of X.  (There are other
problems here such as callbacks, but I don't want to go into that
here).  Much of the X stuff is defined in C header files.  To make use
of these header files within Eiffel requires either a manual or
user-defined automatic translation mechanism.

I don't expect miracles here and I don't expect ISE to come up with
solutions to the problems generated by C language design sins or the
poor coding practice of some C programmers, I just want to point out
that the statement "...in Eiffel too you can easily communicate with C
software; both call-in and call-out are provided" does not tell the
whole story.

Also, with respect to reusing existing software easily, it definitely
is NOT easy to make use of existing X code, particulary existing
widgets.  We've made a serious attempt at it and can do it with some
success, but it is not fun or easy.  And please correct me if I'm
wrong, but having the X-based graphics classes will not make it any
easier to (re)use existing widget sets either.

>
>Simplicity and ease of learning
>
>    Much of the plea for C++ is based on the observation that it provides
>an easy transition from C, which (for better or worse) is the language
>many programmers know nowadays. Using Dr. Brad Cox's expression (meant
>for Objective-C), this supports an ``evolutionary'' approach.
>
>    I can certainly respect this view and its appeal to software managers
>in industry. But I believe that by considering it more closely one will
>find it short-sighted and ill-founded.
>
>    Learning a new language such as Eiffel is nothing for a
>competent programmer. For Eiffel, which is small and simple,
>the learning process typically lasts a few days at most.
>Nobody has ever told us that Eiffel was difficult to learn.
>(If you read this, have tried to learn Eiffel,
>and found otherwise, please respond!) I believe that the process of
>going to Eiffel is in fact much smoother, as you don't have to use
>a confusing mix of old and new concepts.
>In a language that you master totally, you feel
>confident and you can concentrate on your job rather than on
>the language intricacies.

I agree that learning a new language is nothing for a competent
programmer.  However to learn to program effectively and efficiently
in a new language takes much more than a few days, especially if one
is switching paradigms.  Learning to use the language fully and
understand its subtleties is a long term affair.  I have been using
Eiffel for several months and still don't feel like an expert - nor
did I expect that I would.  

One of the obstacles to learning is the lack of a comprehensive
language reference manual.  I was pleased to read that one is
forthcoming.  Another obstacle, which I believe another poster already
stated, is the lack of thorough documentation for the library classes.
At times, I have had to write test programs or actually look at the
source code for the classes to figure out how to use them.  

A case in point is the class H_TABLE.  I wanted to dump the non-null
entries of a an H_TABLE that I created.  I thought that I could loop
through it using entry(i) with i going from 0 to nb_elements-1.
Unfortunately, it wasn't that simple, since entry(i) doesn't return
the non-null entries like I expected it would.  Better documentation
would have prevented me from making this mistake.  Examples in the
documentation could alleviate some of the confusion.

>
>    Also, the brief initial shock produced by the realization that you
>cannot easily write your programs in a traditional way any more is,
>in the experience reported by Eiffel users, highly salutary.
>
But still requires a considerable realignment of ones neurons :-)

--
Jim Gish
GTE Laboratories, Inc., Waltham, MA
CSNET: jgish@gte.com    UUCP:  ..!harvard!bunny!jwg1

jwg1@bunny.gte.com (James W. Gish) (06/07/89)

The following "Hello world" program generated an executable on a Sun3
of 147456 bytes:

class world
inherit
   STD_FILES
feature

   Create is
      do
         putstring( "Hello world." ); new_line;
      end;
end

The .eiffel file used was:

------------ EIFFEL SYSTEM DESCRIPTION FILE -------------------
--   For simple uses, just replace ``root_class_name'' below
--   by the name of the root class of your system (lower case)
ROOT: world
SOURCE: /usr/proj126/Eiffel/library
EXTERNAL:
NO_ASSERTION_CHECK (N):
PRECONDITIONS (N):
ALL_ASSERTIONS (Y):
DEBUG (N):
TRACE (N):
OPTIMIZE (N):
GARBAGE_COLLECTION (N)
VIRTUAL_MEMORY (N)
C_PACKAGE (N):
C_EXTERNAL:
MAKE:
VISIBLE (N):
----------------------------------------------------------------
--
Jim Gish
GTE Laboratories, Inc., Waltham, MA
CSNET: jgish@gte.com    UUCP:  ..!harvard!bunny!jwg1

bertrand@eiffel.UUCP (Bertrand Meyer) (06/07/89)

                        La calunnia: e` un venticello,
                        Un auretta assai gentile
                        che insensibile, sottile
                        incomincia, incomincia susurrar.

(The great Calumny aria from the Barber of Seville)
    

    I have never had any personal business with Dr. Stroustrup.
Any personal hostility is his problem.

    I let readers judge who is insulting whom. For my part,
I have no time to waste on his personal attacks, not a single one
of which is true.

    In my previous message, I stated a fact: Eiffel has been
excluded from a projected OOPSLA panel on the design of object-oriented
languages. This is in the public record and now confirmed by
the party that caused the exclusion. Anyone can judge on the ethics
of the situation.

------------------------

Note: I am writing this just before leaving for a 3-week trip and I cannot
possibly answer the mail messages that I have received recently.
I will try to do so when I come back. I thank all the people who
wrote to me. A few of these messages disagreed on some points
of my technical note, although in my quick review I didn't find
anything that clearly invalidated something I wrote.

     Several people mentioned that I should have included Turing among
the ``commonly available languages'' supporting assertions. I guess
I was not aware that Turing was so commonly available in
universities.  In any case I am happy to correct the omission and
to admit that my Turing could benefit from some brushing up.
-- 

-- Bertrand Meyer
bertrand@eiffel.com

scs@vax3.iti.org (Steve Simmons) (06/07/89)

Various folks have talked about the sizes of linked eiffel and c++
programs.  It all sounds very much like the debate of using or not
using stdio because of the size overhead.  For more built-in features
and libraries, we must pay a price.  [[insert comment about "the
more things change...." here]]

Steve Simmons         Just another midwestern boy
scs@vax3.iti.org  -- or -- ...!sharkey!itivax!scs
"Think of c++ as an object-oriented assembler..."

donahn@gypsum.berkeley.edu (Don Ahn) (06/08/89)

In article <5975@watdcsu.waterloo.edu> mgardi@watdcsu.waterloo.edu (M.Gardi - ICR) writes:
>
>I have heard that eiffel creates hideously large executables from very
>trivial programs. Does anyone have any information as to whether this is 
>true or not?? I found that using advantage C++ also produced large
>executables...one of the reason why I am using Zortech C_++ currently. It does
>not seem to have this problem (executable size seems on average to be about
>1/5 the size of advantage c++ code).
>We're talking 35K here for a hello world program in advantage...something
>that can't be tolerated on the PC. One source gave the comparable eiffel     
>program a number even much higher.

What I'd be more interested in here is the INCREMENTAL increase in executable
size due to program lines/functionality. Given the fact that eiffel has more
functionality in it's run-time environment (built in garbage collection etc..)
it is understandable that for "trivial" programs code size will seem to be
unexplainably huge.

This is not to say that the code size for a "hello, world\n" program is not
completely unimportant.  A extremely large amount of code for a "trivial"
program may indicate an inefficient linker.  But it does not necessary
mean that the compiler is a dog.

A more meaningful comparison to me would be the executable size of two large
"algorithmically equivalent" programs.  Given the power that an OOPS gives
you, re-useable and organized code, it may be possible to DECREASE your
executable size over a non-OOPS language for large programs. Of course, a
well implemented program in a lower-level language (C , assembler) will always
be more efficient than an OOPS.  The problem is, it gets exponentially harder
to create a "well implemented" program as its size goes up in a low level
language.

As I see it, OOPS was created to help make LARGE programs maintainable.
The merits of an OOPS should be measured in this realm.

jos@cs.vu.nl (Jos Warmer) (06/08/89)

In article <JWG1.89Jun6172452@bunny.gte.com> jwg1@bunny.gte.com (James W. Gish) writes:
>
>The following "Hello world" program generated an executable on a Sun3
>of 147456 bytes:
                           [... removed ...]
>The .eiffel file used was:
>
>ALL_ASSERTIONS (Y):
>C_PACKAGE (N):

The size of executables in Eiffel depends very much on the compile options.
The smallest size will be reached when all assertions are turned off.
And all optimizations like inline functions and others are only done
when generating a C package. Using:

ALL_ASSERTIONS(N): ALL
C_PACKAGE (Y): C

gives an executable of 73728 bytes. Using `strip world' gives 57344 bytes.
(Eiffel Version 2.1b, SUN3.5)

Besides, I do agree with Don Ahn:

In article <25321@agate.BERKELEY.EDU> donahn@gypsum.berkeley.edu (Don Ahn) writes:
>
>What I'd be more interested in here is the INCREMENTAL increase in executable
>size due to program lines/functionality. Given the fact that eiffel has more
>functionality in it's run-time environment (built in garbage collection etc..)
>it is understandable that for "trivial" programs code size will seem to be
>unexplainably huge.
   ...
                                 Jos Warmer
				 jos@cs.vu.nl
				 ...uunet!mcvax!cs.vu.nl!jos
-- 
                                 Jos Warmer
				 jos@cs.vu.nl
				 ...uunet!mcvax!cs.vu.nl!jos

marc@eiffel.UUCP (Jean-Marc Nerson) (06/09/89)

>The following "Hello world" program generated an executable on a Sun3
>of 147456 bytes:
>
>class world
>inherit
> 	STD_FILES
>feature
>
>Create is
> 	do
> 		putstring( "Hello world." ); new_line;
>	end;
>end
>

	The same "Hello world" program compiled with Eiffel version 2.2-ALPHA, 
post-processed and all optimizations turned on, 
generates an executable of 64671 bytes (53248 bytes stripped) 
on a Sun386i running O.S 4.0.1 where C libraries are dynamically linked.
	On a Sun3 O.S 3.5 with non dynamically linked C libraries, the size of the
generated code is 73728 bytes (57344 stripped).

	The same "Hello world" program written in C 
on a the Sun386i O.S 4.0.1 is 8645 bytes (4408 bytes stripped)
and on the Sun3 O.S 3.5 it is 32768 bytes (24576 bytes stripped).

	Eiffel run-time libraries are currently not dynamically linked
(this might be in Eiffel 3.0).


Jean-Marc Nerson -- marc@eiffel.com

jans@tekgvs.LABS.TEK.COM (Jan Steinman) (06/09/89)

<mgardi@watdcsu.waterloo.edu (M.Gardi - ICR)>
<A more meaningful comparison to me would be the executable size of two large 
"algorithmically equivalent" programs.>

We have an application that is implemented in both Smalltalk and 
C++/Interviews/X11.  When compiled with debugging on, the C++ version is much 
slower and nearly as large as the whole Smalltalk image, which contains much 
more functionality, and always has debugging available.

This is not meant to start any kind of war, simply to point out than many 
comparisons of the sort compare apples with oranges.  With debugging off, the 
C++ version is about 1/6 the size of the whole Smalltalk image, although 
graphics performance is still slower -- probably due to the many layers of 
software needed, while Smalltalk is able to BitBlt.

:::::: Jan Steinman - N7JDB		   Electronic Systems Laboratory ::::::
:::::: jans@tekgvs.LABS.TEK.COM	      Box 500, MS 50-370 (w)503/627-5881 ::::::
:::::: jsteinma@caip.RUTGERS.EDU     Beaverton, OR 97077 (h)503/657-7703 ::::::

plogan@mntgfx.mentor.com (Patrick Logan) (06/09/89)

In article <1989Jun6.171549.16028@utzoo.uucp> henry@utzoo.uucp (Henry Spencer) writes:
:)   In article <233@pink.ACA.MCC.COM> rfg@pink.aca.mcc.com.UUCP (Ron Guilmette) writes:
:)   >For me, Eiffel  was kind of like a chastity belt.  It definitely keeps
:)   >you "pure" but you will probably have less fun. :-)
:)
:)   It struck me, in fact, that a good many of Dr. Meyer's comparisons between
:)   C++ and Eiffel boiled down to "C++ lets the programmer foul things up in
:)   any way he pleases, while Eiffel insists on doing it right".  This is, in
:)   fact, a long-standing philosophical difference between the C camp and the
:)   Pascal camp.

Instead of the phrase "doing it right" I think it would be more fair
to paraphrase with "doing it according to some principles of sound
software construction."  As I read it, the phrase "doing it right"
carries more self-righteousness than I felt existed in the original
article. The article mentioned or referred to the guiding principles.

:)   The Pascal side favors using the language to impose discipline, which makes it
:)   a LOT easier to get reliable, well-behaved programs but can make it harder
:)   to get the desired results with those programs.  Which set of tradeoffs is
:)   better depends on the circumstances and the people.
:)
:)   (Me?  I find the Pascal theory very attractive but at the moment am fully
:)   in the C camp for pragmatic reasons.  Combining the virtues of the two
:)   ought not to be impossible but seems to be difficult in practice.  Perhaps
:)   a mixed approach is better than trying to pick one or the other.)
:)   -- 
:)   You *can* understand sendmail, |     Henry Spencer at U of Toronto Zoology
:)   but it's not worth it. -Collyer| uunet!attcan!utzoo!henry henry@zoo.toronto.edu

The logic here seems to be the following:
    The argument of C++ vs. Eiffel is similar to the typical C vs. Pascal argument.
    Therefore Eiffel is in the Pascal "camp".
    Therefore Eiffel will have the same problems as Pascal.

I wouldn't consider this sound logic. Its application could lead
someone away from even attempting to evaluate Eiffel.

-- 
Patrick Logan                | ...!{decwrl,sequent,tessi}!mntgfx!plogan 
Mentor Graphics Corporation  | plogan@pdx.MENTOR.COM                    
Beaverton, Oregon            | "My other computer is a Lisp machine."

bs@alice.UUCP (Bjarne Stroustrup) (06/10/89)

I stated in an earlier message that I was unwilling to share a stage
with Bertrand Meyer because of his grossly impolite and insulting
behavior toward me, my friends, and professional colleagues.
He replied that my claims are groundless.

Clearly we cannot both be telling the truth. Many people who attended
ECOOP'87, and some who attended OOPSLA '88, are in a position to know
for themselves which of us is lying. Others can read this whole
distasteful series of exchanges starting with Bertrand Meyer's
original posting and make a guess. Bertrand Meyer's company's use of
AT&T's name and quotes from my copyrighted works in its advertising
(without permission, of course) is also available for all to see.

The present exchange is in itself a good example of why I prefer to
have as little as possible to do with Bertrand Meyer.  He has too
often failed to attain the minimal standards of common courtesy and
detachment from commercial concerns necessary for a technical exchange.

For example, `part two' of his technical comparison of C++ and Eiffel
contained a litany of unfounded accusations using extreemely loaded
vocabulary: `censorship, money, power, intimidation, hype, one-sided
propaganda, scared indeed, suppressed, pre-settled panels, biased
articles, trying to crush.'

	- Bjarne Stroustrup

PS By replying to his postings I did enter into a public discussion with
Bertrand Meyer. That was probably a mistake, but I considered it a very
real danger that unanswered accusations could become accepted `fact.'

bigm@batserver.cs.uq.oz (Michael Pilling [Real people drink purple milk]) (06/11/89)

Larry Morris in a recent article writes

> > can talk about the very idea of reusable software components without
> > assertions...
> > maintained by the amplifier). Yet of widely available programming
> > languages, only Eiffel has these notions.
> Assertion checkers, of course, have been used for years as tools outside
> the scope of the language, as libraries, or extracted by tools from
> code comments. Placing assertions within classes as part of the language
> is, I must agree, a very powerful feature. But Eiffel's design philosophy
> calls on programmers to define their classes with assertions in addition
> to coding their implementation; something most programmers aren't used to
> doing and may view as an onerous task. Since assertion checking isn't any
> better than the assertions dreamed up by the programmer, I'm skeptical of
> using it to "replace" unit testing.

I have been encouraging my group software project students to use assertions,
and have found that they take some time to get into the swing of writing
effective and prudent assertions. This feeling is based on their reactions,
I have yet to mark their code (uggggh). Like anything there is a learning
curve and a few people will never really get the hang of it. This is not
to say assertions are a bad feature, it mearly reveals those who should
should be programming and those whose talents lie in other areas. (Perhaps
they could help me with my spelling :-) )

I have been using assertions for 3 years and felt obliged to point out
that they are not intended to "replace" unit testing but to simplify and
augment it. I have found assertions to have the following benifits in
whatever language you choose to implement them.

1. Carefully chosen assertions clarify your understanding of the code
   you are writing or reading and force you to reason about what you
   are really doing and it's consequences. I have found this to be
   the most important benifit. It allows you to produce clearer, simpler
   and more efficient CORRECT code.

2. Error detection is increased. You can't fix them if you don't find
   them. In a large library module, certain code may never be executed
   until it fails. This may be 2 or 5 years down the track. Or the error
   may not manifest 99% of the time because one errornous result in a 
   record/structure is only occasionally accessed. Assertions add another
   layer of testing - those of self consistency and plausability
   e.g.s
     While traversing a doubly linked list you can assert that the
     current link points back to where you came from.

     A positive square root should be smaller than the input and
     when squared should give the input.

3. Errors are detected close to their occurence in space and time.
   Symptoms of the error may be much further away when the real causes
   have been obscured. This makes fixing the bug easier because you don't
   have to waste so much time looking for it.
   e.g.
	Space - Assertions fail in your binary search routine - jumping
                to the bottom half of the array actually gave you a
                smaller key!! Conclusion: The caller lied when they claimed
                the array was sorted. Saved from wasting time trying to
		debug the correct binary search routine.
   
	Time -  Stange errors are occurring in your program. You suspect
		the memory arena's been trashed but have no idea who did it
		and when. Assertions can often detect the culprit soon after
		they commit the crime.

4. When you think you've fixed the bug the saftey net is still there to
   tell you you were wrong. In libraries this to can be useful to detect
   bugs in infrequently used code rather than letting them slip through
   unnoticed.

5. They can make programs more robust and protect data
   by stopping their progress in emergancy situations.
	Real Life example:
		Data General AOS/VS operating system utility "Exec" hung itself
		after uttering: Internal inconsistancy error -
				negative time encountered.
		In reality, one of the sysops had corrected the time of day
		because it was fast. Exec caught itself completing a task before
		it started and thought the clock hardware had failed.
		It correctly aborted system processing rather than risk damaging
		timestamps used for backups and other data consistancy functions.

6. You can avoid buggarising your code with error handlers. Why should you
   attempt to clean up other peoples mistakes. Your code is simpler and
   more likely to be correct.
	eg
		When I did the group software project I was the only one to
		use assertions.  During intergration, people would run to me
		saying YOUR module had ANOTHER assertion failure.  More often
		than not, I had the pleasure of replying "Oh, that means your
		not sorting that array you passed me like you were supposed to."

I have personally found the use of assertions to save me 80% of my previous
debugging time and effort. They allow you to tackle problems that would be
almost insumountable otherwise, particularly when useing malloc & free.
Like any good investment they pay many returns over a long period.
Assertions should be included in the language (definition and compiler proper)
so you can turn them off (at your own risk). Preprocessed assertions often
produce much more code per assertion and can not check that your assertions
do not have side effects. (Side effects prevent you from turning them off
because you program behaves differently.)

Michael Pilling,
Computer Science Department,
University of Queensland,	
St Lucia, 4067	Australia.		

ark@alice.UUCP (Andrew Koenig) (06/12/89)

In article <807@batserver.cs.uq.oz>, bigm@batserver.cs.uq.oz (Michael Pilling [Real people drink purple milk]) writes:

>      A positive square root should be smaller than the input and
>      when squared should give the input.

Sometimes the code is right and the assertion is wrong.

For example, sqrt(0.25) should be 0.5
-- 
				--Andrew Koenig
				  ark@europa.att.com

dan@oresoft.uu.net (Daniel Elbaum) (06/13/89)

Gee, this discussion reminds me--C is really a much better
programming language than Pascal.  You all agree, don't you?
-- 
The workaday world must remain transparent to those who maintain it if
they are to find inspired within them a vision of the history they create.

({uunet,tektronix,reed,sun!nosun,osu-cis,psu-cs}!oresoft!(dan)@oresoft.uu.net)

db@lfcs.ed.ac.uk (Dave Berry) (06/13/89)

In article <150@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>    C++ has a notion of friend function which, as I understand it, makes
>it possible to define routines outside of the object-oriented framework.
>There is nothing equivalent in Eiffel. This facility is not missed.

In C++ a class A may define other classes to be its friends; these classes 
can access all attributes and members of A.  From the book (OOSC), Eiffel
does seem to have an equivalent, namely the facility where members may be
exported to certain named classes only.  Both mechanisms allow A to control
access to part of itself.  The Eiffel mechanism gives finer control.
I don't know if this finer control will matter in practice.

Friend functions in C++ are similar, but allow the integration of object
oriented software with non-OO software, in keeping with the rest of the
language.

>Compatibility with C means that in C++ you still have pointers, type casts,
>pointer arithmetic, function pointers, malloc, free.  I strongly disagree
>with this approach if the goal is to obtain software quality.  In Eiffel,
>the choice has been made. None of these low-level features are present;
>needless to say, they are not missed.

Except by all the people asking for them on USENET ( semi :-) ).
I would say that languages don't encourage software quality if they require
the use of low-level features unnecessarily.  C & C++ undoubtably do so,
although C++ will improve when type parameterisation and multiple inheritance
are available.  This doesn't mean that such features should not be provided.
Sometimes some people need low-level control.  What is important is that they
should be able to hide their use of such features from the rest of the program.

I find it odd that Meyer considers function pointers "low-level".  There was
some discussion of function parameters in Eiffel a couple of months ago, and
they seemed to offer neater solutions (IMAO) to some problems than the
alternative techniques.  Treating functions as first order objects (or
"nearly firat order" objects) is usually considered high level.

Dave Berry, Laboratory for Foundations      db%lfcs.ed.ac.uk@nsfnet-relay.ac.uk
    of Computer Science, Edinburgh Uni.	    <Atlantic Ocean>!mcvax!ukc!lfcs!db

       Britain without the Queen is like a democracy without a monarch.

geof@nswitgould.OZ (Geoffrey Jones) (06/14/89)

In article <11991@nswitgould.OZ>, I wrote:
> As a small issue in C++'s favour, each C++ class
> can contain a destructor routine which is executed whenever an object
> of that class is destroyed, which will be whenever the object goes out
> of scope (e.g., at program termination) or whenever it is actively
> deallocated from the dynamic memory pool. No such operation exists in
> Eiffel. This makes certain types of programming awkward in the latter.

Oh dear, searching through my comp.lang.eiffel archive I grepped on
"destructor" and found to my surprise that Jos Warmer (jos@cs.vu.nl)
had already raised this point in article <2152@vlot.cs.vu.nl>. I'll
include a little of it here because the article has probably expired
from most sites by now and many comp.lang.c++ people following this
discussion won't have read it before:

> Some problems with garbage collection:
> 
> 1. In the library class FILE one can create a FILE object, open it and use it.
>    If the FILE object is not referenced anymore, the memory used by it
>    will be reclaimed by the garbage collector.
>    However, each file that is opened should be closed before the FILE object
>    is destroyed.
> 
>    This can not be forced by the FILE class, but it is left to the client.
>    It should be much safer if the FILE class could ensure that each file
>    is closed before the object pointing to it is destroyed.
>
     [ ... much more removed ... ]
>
> A possible solution:
> 
> In C++ so-called destructors can be defined.  A destructor is a routine
> that is called on an object when the object is being freed.
> A destructor contains code that performs some cleanup before the object
> is destroyed.
> 
> These destructors can be used to solve the problems described above.
> I cannot find a way to solve these problems in eiffel.  Should such
> a feature be added eiffel, or are there other solutions.

In article <129@eiffel.UUCP> Bertrand Meyer (bertrand@eiffel.UUCP)
follows up to provide a (patch) solution:

>     In version 2.2 the library class MEMORY will include an argumentless
> procedure called dispose, to be invoked by the garbage collector (if
> active) when an object is freed. The original version of this class
> has an empty body and hence does nothing. Any class can inherit
> from MEMORY and redefine this procedure to do something, for instance
> close a file as in Mr. Warmer's example.
> 
> Two caveats:
> 
>     - The exact details are still subject to change.
> 
>     - The next version (Eiffel 3, end of 1989) will support the
>     possibility of treating all objects as persistent (the set of all
>     objects of an Eiffel session becoming a database). In this context
>     the problem addressed by Mr. Warmer becomes part of a larger
>     requirement (describing what should be done to any object when
>     the session terminates, or when it is stored to a file by an automatic
>     mechanism). This means that the 2.2 solution may be overridden at that
>     time by a more general scheme.

The version 2.2 solution is indeed a step in the right direction but I
don't see that it should be the final answer. An "obvious" solution
might be to imbue Eiffel's `Forget' with an enlarged semantics, thus
moving the solution under the auspices of the language definition and
away from all the ad hoccery involving strange class inheritences.  I
would propose that programmers could define their own `Forget'
routines analogously to programmer-defined `Create's.  Thus the
responsibility to call server class terminating routines (e.g.,
`close' in class FILE) would be removed from the server's clients (as
Dr Meyer's v2.2 solution seems to allow), as well as from the vagaries
of the garbage collector which may or may not be active depending on
all sorts of contingencies not the least of which is whether the GC was
enabled at compile-time(!). I believe it would be proper if each class
instance had its programmer-defined Forget routine called whenever
that instance went out of scope of all other system objects, i.e., if
a successful garbage sweep of the object could be made or whenever the
program was terminating.

Naturally these are only tentative thoughts which should be weighed in
the light of added language complexity and so forth. However the
problem of proper object termination is a real one that must be
addressed in the not-too-distant future if Eiffel is to become a
suitable platform for many types of computing tasks.

Geof.

----------------------------------------------------------------------------
Geoffrey Jones            ACSnet: geof@nswitgould.oz.AU
Dept. of Computer Science ARPA:   geof%nswitgould.oz.AU@uunet.UU.NET
U. of Technology, Sydney  UUCP:   ...!munnari!nswitgould.oz.AU!geof
P.O. Box 123,             Or try: munnari!nswitgould.oz.AU!geof@uunet.UU.NET
Broadway, 2007                
AUSTRALIA                 Phone: (02) 218 9505
----------------------------------------------------------------------------

diamond@diamond.csl.sony.junet (Norman Diamond) (06/14/89)

In article <807@batserver.cs.uq.oz>, bigm@batserver.cs.uq.oz (Michael Pilling [Real people drink purple milk])
drank something purple that wasn't just milk:

>>      A positive square root should be smaller than the input and
>>      when squared should give the input.

In article <9464@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:

>Sometimes the code is right and the assertion is wrong.
>For example, sqrt(0.25) should be 0.5

This is entirely correct, of course.  Nonetheless, suitable use of
assertions make it much easier to debug both the assertions and the
code, than it is to debug code by itself.

--
Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.co.jp@relay.cs.net)
 The above opinions are my own.  However, if you see this at Waterloo, Stanford,
 or Anterior, then their administrators must have approved of these opinions.

rpj@mcc.com (Rich Johns) (06/14/89)

   With debugging off, the 
   [C++/InterViews/X11] version is about 1/6 the size of the whole Smalltalk image,
   although graphics performance is still slower -- probably due to the many layers of 
   software needed, while Smalltalk is able to BitBlt.

What X11 server are you using? If its on a sun3, for example, I can
see why the performance is slow. Also, I believe that InterViews 2.5
has BitBlt capability.

Rich Johns, MCC CAD Program | 3500 W. Balcones Center Dr., Austin, TX 78759
ARPA: johns@mcc.com         | Phone: [512] 338-3714
UUCP: {uunet,harvard,gatech,pyramid}!cs.utexas.edu!milano!cadillac!johns

mjl@cs.rit.edu (06/15/89)

In article <9456@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) writes:
>Bertrand Meyer's company's use of
>AT&T's name and quotes from my copyrighted works in its advertising
>(without permission, of course) is also available for all to see.

I don't want to get bogged down in the name calling and other
vituperative rantings and ravings that have been going on in these
newsgroups, but this sentence intimates that ISE and Dr. Meyer have
done something improper with Dr. Stroustrup's work and AT&T's name.  I
assume Dr.  Stroustrup refers to ads such as the one in the July 1988
issue of IEEE Software (inside the front cover).  If so, then two
points must be made:

1. Three of the four quotes refer to an article by Dr. Stroustrup in IEEE
Software, and, as a member of the editorial board, I know that the copyright
belongs to the IEEE (this is standard policy).

2. All of the quotes are short, and properly cited in the ad.  As such, they
are covered by the fair use doctrine, and ISE has done nothing improper
in using them.  I'll leave it to others to determine whether or not the
quotations were used out of context.

3. The only reference to AT&T is in a footnote attached to a table comparing
C++ to Eiffel, and simply is used to document the version of the C++ compiler
used in the comparisons.  Rather than slandering AT&T, this provides a
service to readers of the ad.

In short, there seems to be little basis for this particular complaint.
Mike Lutz	Rochester Institute of Technology, Rochester NY
UUCP:		{rutgers,cornell}!rochester!ritcv!mjl
CSNET:		mjl%rit@relay.cs.net
INTERNET:	mjl@cs.rit.edu

jeff@aiai.uucp (Jeff Dalton) (06/19/89)

In article <150@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:
>From article <2689@ssc-vax.UUCP> by dmg@ssc-vax.UUCP (David Geary):

>Eiffel software is organized in autonomous software units (classes),
>meant to be compiled separately. There is no main program.  [...]  In
>contrast, I understand that C++ still follows the traditional C model.
>[...]  ``A C++ program typically consists of many source files, each
>containing a sequence of declarations of types, functions, variables,
>and constants''. This is very far from the object-oriented model of
>software decomposition.

It is true that C++ does not enforce object-oriented decomposition
or provide explicit support for it.  Nonetheless, a C++ programming
environment could provide such support.  And it is possible to make
reasonable decompositions in C and C++, even though the compilation
units are files, and even without any special environmental support
that "hides the files".

So I don't think C++ prevents the programmer from doing objet-oriented
decomposition, but I'll have to leave the details to those who know
more about C++ than I do.

>Multiple inheritance
>
>    Multiple inheritance is fundamental in the Eiffel approach. We made
>every effort to handle it in a very clean way; name clashes, in particular,
>are treated in what I believe is the right way. (More precisely, I do not
>know of any satisfactory solution in any other language. This is a strong
>statement, and proponents of other languages are welcome to respond to the
>challenge.)

I think the statement is too strong as it stands, because "satisfactory"
isn't defined.  It also makes it difficult for other languages to
respond to the challenge.

But I'm not sure it's possible to make strong conclusions in any case.
Suppose someone said the Eiffel solution was unsatisfactory.  How could
this be resolved?  IN the end you may just have different goals.

>Garbage collection

>As far as I know, C++ systems do not support garbage collection,
>which would be extremely difficult if not impossible to implement
>because of the presence of C types and mechanisms.

As far as I know, it is possible to provide garbage collection for C,
and some systems have actually done so.  The GC has to be "conservative"
in that it must regard anything that might be a pointer as a pointer.
So there might be some garbage it can't collect, but it will never
collect non-garbage.

It is possible to write some things in C that will cause such systems
to go wrong, but (again, as far as I know), all such things are regarded
as nonportable.  So conforming programs can't do them.

-- Jeff

jeff@aiai.uucp (Jeff Dalton) (06/19/89)

In article <89155.092349UH2@PSUVM> UH2@PSUVM.BITNET (Lee Sailer) writes:
>the address, and thus cannot optimize well.  The same argument has
>been made about strings---C does NOT have a string type.  We fake it
>with pointers (addresses) and arrays (pointers 8-).  In a language
>that does have a specific string data type, the compiler writer has
>a chance to do some optimization tricks otherwise not available.

I think this may be a more complex issue than it at first appears.
Richard O'Keefe has argued on several occasions that string processing
is more efficient when there isn't a built-in string type.  I'm not
sure he's correct, but he generally knows what he's talking about.

(I'm sorry I don't have any "real" references -- there were just
some articles in Comp.lang.c (I think) and Comp.lang.prolog.)

jimp@asterix.UUCP (Jim Patterson) (06/24/89)

In article <12031@nswitgould.OZ> geof@nswitgould.OZ (Geoffrey Jones) writes:
>In article <129@eiffel.UUCP> Bertrand Meyer (bertrand@eiffel.UUCP)
>follows up to provide a (patch) solution:
>
>>     In version 2.2 the library class MEMORY will include an argumentless
>> procedure called dispose, to be invoked by the garbage collector (if
>> active) when an object is freed.
>
>The version 2.2 solution is indeed a step in the right direction but I
>don't see that it should be the final answer. An "obvious" solution
>might be to imbue Eiffel's `Forget' with an enlarged semantics, thus
>moving the solution under the auspices of the language definition and
>away from all the ad hoccery involving strange class inheritences.  I
>would propose that programmers could define their own `Forget'
>routines analogously to programmer-defined `Create's.  

This suggestion ignores the significant difference between Eiffel's
Forget builtin feature and more direct memory management primitives
such as C's free. Forget simply clears a reference to an object; it's
still left up to the garbage collector to actually free the object,
and then only if there are not other references. If Forget were
changed to actually dispose of the object (or to perform cleanup
code), then other references to that object within the program
would suddenly became invalid. This negates the major benefit of
a garbage collector, which is to relieve the programmer of the
burden of tracking which objects are or are not still accessable.

Dispose is the more appropriate solution, as it supports an arbitrary
number of references to any object so that the Dispose procedure
is only actually called when there are no remaining references.
One drawback is that the actual timing of a Dispose call is somewhat
arbitrary; this must be considered when designing the class.
-- 
Jim Patterson                              Cognos Incorporated
UUCP:decvax!utzoo!dciem!nrcaer!cognos!jimp P.O. BOX 9707    
PHONE:(613)738-1440                        3755 Riverside Drive
                                           Ottawa, Ont  K1G 3Z4

bertrand@eiffel.UUCP (Bertrand Meyer) (06/29/89)

From <233@pink.ACA.MCC.COM> rfg@pink.aca.mcc.com.UUCP (Ron Guilmette),
quoted by later messages:

>> For me, Eiffel  was kind of like a chastity belt.  It definitely keeps
>> you "pure" but you will probably have less fun.
>> It struck me, in fact, that a good many of [B. Meyer]'s comparisons between
>> C++ and Eiffel boiled down to "C++ lets the programmer foul things up in
>> any way he pleases, while Eiffel insists on doing it right".  This is, in
>> fact, a long-standing philosophical difference between the C camp and the
>> Pascal camp.

    The debate, which is older and broader than the question of C versus
Pascal, is indeed an important one: How restrictive and prescriptive
may a language designer be in forcing a particular approach to software
construction upon the users of the language?

    However their application to the design of Eiffel may be judged,
I can at least clarify my intentions.

1. ``Chastity belts'' are inappropriate. A chastity belt prevents its
holder from doing things that are desirable and enjoyable. A language
designer is not a guardian of moral order.

2. A good programming language is one that helps programmers write good
programs. No programming language will prevent its users from writing bad
programs.

    [If I recall correctly, this is an observation I first heard
    a long time ago from Kees Koster, who among other things
    is the designer of the CDL language.]
 
3. Some constructs are known to be dangerous, meaning that programs
employing them are prone to contain damaging errors.
In any language meant for industrial production, it is the language
designer's responsibility to exclude such constructs.

    Examples include type casts, user-controlled memory deallocation,
pointer arithmetic, in-line functions (in an object-oriented language)
etc.

4. The purpose of excluding a construct is not to prevent
programmers from writing bad programs or doing ``dangerous things'' if
they want to. (See points 1 and 2.) Instead, a construct is excluded
because it is known to lead programmers to make mistakes even when
applied towards legitimate goals.

    This highlights the basis for all this discussion. In the same way
that the author of a novel has a typical reader in mind, the designer
of a programming language is, consciously or not, designing for
a typical programmer. We should assume (as was done for Eiffel)
that this typical programmer is intelligent and reasonable.
The restrictive parts of the language design are not meant to prevent
the programmer from being ``bad'', but rather to help him avoid
known pitfalls and involuntary mistakes.

5. For the language designer, excluding a construct is not a solution
but a problem.

    In all likelihood the excluded construct addressed some legitimate
need, albeit in an inadequate way. The designer must find a better
technique to satisfy the same need. This is the difficult part, of course:
exclusion is easy. Sometimes the solution is a better programming
language construct; in other cases the problem is best handled by the
implementation  (compiler and programming environment).

    For example, unrestrained type casts may be replaced by
inheritance-controlled polymorphism; garbage collection should be under
the control of the run-time system; pointer arithmetic is unneeded in the
presence of type-safe dynamic binding; and in-line routine expansion
should be the responsibility of an optimizing compiler. 

6. Literal compatibility with previous languages should not be a
criterion. People will learn a new language quickly if its design is
simple and consistent. One should learn from the mistakes of the past, not
perpetuate them.

    Some care should be exercised, however, when one deals with programmers'
current habits. For example, a new language should not use an existing
notation in a way that confusingly departs from its accepted semantics.
(The Eiffel assignment operator, :=, is a case in point;
its semantics would probably have been different were it not for the fear
of confusing Algol-Pascal-Ada programmers.)

7. Perhaps my major personal guideline is to maximize the signal-to-noise
ratio of the language.

    Exclude constructs that just add complexity to the language without
bringing any significant new possibility (for example, varieties of
loops); include constructs that tersely and elegantly address a large number
of practical situations.

8. Any occurrence in a language description of a sentence of the form
``Be careful when using this construct'' implying that its use may have
dangerous consequences, is an avowal of failure on the designer's part.
Programmers should be encouraged to use the entire language, not a subset.

    The programming language is the software developers' fundamental tool.
They should know, love and trust all of it.

9. Hard as you try to maximize the signal-to-noise ratio, there may remain
cases in which special needs require special facilities.

    Such special facilities should be limited to only one situation:
the need to access low-level internal or machine-dependent elements.
In my opinion, this is best addressed by techniques that
fall outside of the language proper, such as machine-code insertions in
Ada or external routines in Eiffel.

    To avoid violating the previous criterion (8), there should be very
few such techniques, and they should never be needed in normal uses
of the language. In Eiffel their typical uses have been encapsulated in
the library (essentially in the class called INTERNAL) and their application
is limited to the following cases:

    - Interfacing with elements on which the language design has no
    control: existing software tools (for example, relational data base
    management systems) or software written in other languages.
    
    - Machine-dependent programming.

    - Implementation of facilities which are part of the basic environment
    (such as the ARRAY and STRING classes in the kernel Eiffel library).

    - Facilities which the language designer feels are not necessary, while
    recognizing that some language users may disagree on this point. There
    is one example of this in Eiffel: class INTERNAL contains a procedure
    ``free'' which will explicitly return an object to the free store.
    In our opinion it should never be used, and none of our own software
    ever uses it; however we accept that some users may disagree and would
    rather provide the corresponding facility in an ``official'' form
    than encourage these users to fool around with internal formats.

                        ***

    In summary, the aim of what Mr. Guilmette calls a more ``pure'' design
is not to prevent programmers from ``fouling things up'' but to enable them to
do things in a way that is at the same time safer, more elegant, more
powerful and more convenient. Reconciling these goals is the main challenge
in designing a better programming language.

    Coming back to the first two lines of his extract:

>> For me, Eiffel  was kind of like a chastity belt.  It definitely keeps
>> you "pure" but you will probably have less fun.

Eiffel programmers can have fun, too, thank you. Of course, someone whose idea
of fun is to spend his or her nights debugging will have less of it.
But then such a person wouldn't need a chastity belt anyway.


-- Bertrand Meyer
bertrand@eiffel.com

nevin1@cbnewsc.ATT.COM (nevin.j.liber) (07/06/89)

Disclaimer:  these are my PERSONAL opinions, period.  I agree with some
of the points; I am mainly commenting on those I disagree with.

In article <166@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:

|3. Some constructs are known to be dangerous, meaning that programs
|employing them are prone to contain damaging errors.
|In any language meant for industrial production, it is the language
|designer's responsibility to exclude such constructs.

|    Examples include type casts, user-controlled memory deallocation,
|pointer arithmetic, in-line functions (in an object-oriented language)
|etc.

Unfortunately, stuff like type casts and user-controlled memory
management tend to be useful in many contexts.

|4. The purpose of excluding a construct is not to prevent
|programmers from writing bad programs or doing ``dangerous things'' if
|they want to. (See points 1 and 2.) Instead, a construct is excluded
|because it is known to lead programmers to make mistakes even when
|applied towards legitimate goals.

But, as a USER, I really don't care what the *purpose* behind doing
something is.  For example, the *purpose* behind putting in ramps in
sidewalks wasn't to allow kids to ride their bicycles into traffic
without having to stop like they had to for curbs, yet that was the
*result*.

|The restrictive parts of the language design are not meant to prevent
|the programmer from being ``bad'', but rather to help him avoid
|known pitfalls and involuntary mistakes.

But they DO prevent the programmer from being ``bad''; that is the
price that is being paid in order to help him avoid known pitfalls and
involuntary mistakes.

|6. Literal compatibility with previous languages should not be a
|criterion. People will learn a new language quickly if its design is
|simple and consistent. One should learn from the mistakes of the past, not
|perpetuate them.

|    Some care should be exercised, however, when one deals with programmers'
|current habits. For example, a new language should not use an existing
|notation in a way that confusingly departs from its accepted semantics.
|(The Eiffel assignment operator, :=, is a case in point;
|its semantics would probably have been different were it not for the fear
|of confusing Algol-Pascal-Ada programmers.)

Keeping 6 in mind, and assuming that you wanted to give the Eiffel
assignment operator different semantics than those given by
Algol/Pascal/Ada to ":=", why didn't you just pick another symbol (eg:
".=")?  Please elaborate.

|7. Perhaps my major personal guideline is to maximize the signal-to-noise
|ratio of the language.

|    Exclude constructs that just add complexity to the language without
|bringing any significant new possibility (for example, varieties of
|loops); include constructs that tersely and elegantly address a large number
|of practical situations.

But varieties of loops, if used correctly (admittedly, a big if), can
add to the self-documenting aspect of a language.


This whole discussion reminds me of an early paper by Wirth which I
read a while back (I wish I could find that paper :-().  In it, he
spends the first half describing his ideal programming language, which,
to me, seemed close to C, and then spent the second half saying that it
was unusable because you couldn't guarantee safety.
-- 
NEVIN ":-)" LIBER  AT&T Bell Laboratories  nevin1@ihlpb.ATT.COM  (312) 979-4751

bertrand@eiffel.UUCP (Bertrand Meyer) (07/07/89)

From <1559@cbnewsc.ATT.COM> by nevin1@cbnewsc.ATT.COM (nevin.j.liber):

[Quoting from my previous message: ]

> |    Some care should be exercised, however, when one deals with programmers'
> |current habits. For example, a new language should not use an existing
> |notation in a way that confusingly departs from its accepted semantics.
> |(The Eiffel assignment operator, :=, is a case in point;
> |its semantics would probably have been different were it not for the fear
> |of confusing Algol-Pascal-Ada programmers.)


> [...] Assuming that you wanted to give the Eiffel
> assignment operator different semantics than those given by
> Algol/Pascal/Ada to ":=", why didn't you just pick another symbol (eg:
> ".=")?  Please elaborate.



[Perhaps :-) would do for assignment?] :-)

	Actually the Eiffel convention is the same as the Pascal and Ada
ones for entities of pointer/access/reference types, which is the reason
for keeping the same notation.

	In general it seems proper to avoid inventing a new notation
where there is no real semantic innovation and a widely accepted notation
exists, unless there are strong arguments against that notation. (An
example of the latter would be the Fortran/C use of = for assignment,
which conflicts with time-honored mathematical conventions.)
The language should look familiar in places where the concepts are indeed
familiar. There are a number of novel ideas in Eiffel, but assignment
is a quite standard concept. As one may expect, the properties of
assignment in Eiffel are not identical to those of its counterparts in
previous languages, but the differences do not seem big enough to warrant
a totally new notation. Call it lack of courage if you will.


-- Bertrand Meyer
bertrand@eiffel.com

pcg@thor.cs.aber.ac.uk (Piercarlo Grandi) (07/09/89)

In article <168@eiffel.UUCP> bertrand@eiffel.UUCP (Bertrand Meyer) writes:

   From <1559@cbnewsc.ATT.COM> by nevin1@cbnewsc.ATT.COM (nevin.j.liber):

   > [...] Assuming that you wanted to give the Eiffel
   > assignment operator different semantics than those given by
   > Algol/Pascal/Ada to ":=", why didn't you just pick another symbol (eg:
   > ".=")?  Please elaborate.

   [Perhaps :-) would do for assignment?] :-)

Remember this line for later on...

	   Actually the Eiffel convention is the same as the Pascal and Ada
   ones for entities of pointer/access/reference types, which is the reason
   for keeping the same notation.

Ugh. I beg to differ. Pascal and Ada have a concept of pointer,
and indeed := is used by them to do *copy* of pointer objects. This
is VERY different from Eiffel. The analogy cannot hold.

	   In general it seems proper to avoid inventing a new notation
   where there is no real semantic innovation and a widely accepted notation
   exists, unless there are strong arguments against that notation.

Eiffel, by doing without a concept of pointer (except by hack)
and by having reference and copy assignments both under := blurs
the distinction between EQ and EQUAL, that lispers know as being
very fundamental.

   As one may expect, the properties of assignment in Eiffel are not
   identical to those of its counterparts in previous languages, but
   the differences do not seem big enough to warrant a totally new
   notation. Call it lack of courage if you will.

Ahhh! Let me exhume old ghosts... Simula67 uses := for
assignment, and :- for reference assignment. You would have
invented nothing new, and adopted a well known tradition, if you
had used :- for reference (in the Simula67 sense) assignment.

Also, I am incredibly amused by the idea that actually :- *is* the
leading part of :-)...

	NOTE: I find it worrying that the author of Eiffel, a person that
	I greatly esteem, is not extremely familiar with Simula67 and Lisp.
	Now some embarassing questions: Has he ever read the Simula67
	Common Base standard? Simula BEGIN? What is Hash Consing and how
	does it relate to this discussion? What is rplac[ad] and how does
	it relate to this discussion?

		NOTE on NOTE: many will have noted (:->) that one of my pet
		peeves is moaning about the lack of historical perspective
		by most computer scientists (especially, let me say, American
		(ised :->) ones wrt much European research). I apologise
		in advance for the irritation this mania causes...
--
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk

bertrand@eiffel.UUCP (Bertrand Meyer) (07/10/89)

From article <PCG.89Jul8222705@thor.cs.aber.ac.uk>, by pcg@thor.cs.aber.ac.uk:

> Pascal and Ada have a concept of pointer,
> and indeed := is used by them to do *copy* of pointer objects. This
> is VERY different from Eiffel.

	Unless there is something I don't understand I am afraid Mr. Grandi
is mistaken. Both in Pascal and in Ada := is used for pointer assignment.
For Pascal, see chapter 10 of Pascal User Manual by Kathleen Jensen and
Niklaus Wirth, Springer-Verlag, 1974 (pages 62-66 in the second edition);
also the ``Report'' part of the same book, section 7.3. For Ada, the relevant
section of the Reference Manual (3.8) is not the most luminous piece of
technical literature ever written, but there is no doubt that the semantics
is indeed that of pointer assignment. (See for example ``Ada for Experienced
Programmers'' by A. Nico Habermann and Dewayne E. Perry, Addison-Wesley,
1983, page 197.)

	Interestingly enough, Pascal and Ada both also use := to prescribe value
assignment for referenced records. I believe the correct notations are
p^ := q^ in Pascal and p.all := q.all in Ada.

	As explained in my article on ``Eiffel types'', there are cases in
which one *explicitly wants* to have the same symbol express different
semantics for reference types and expanded types. (The latter is Eiffel 2.2
terminology for types whose elements are objects rather than references to
objects; expanded types include the basic types INTEGER, REAL, DOUBLE etc.)
Thanks to expanded types and the associated assignment and
argument passing conventions, Eiffel 2.2 allows programmers to choose
exactly what they need in a given case: uniform copy semantics, or
variable semantics. This is particularly important for generic classes.

> 	I find it worrying that the author of Eiffel [...]
> 	is not extremely familiar with Simula67 and Lisp.
> 	Now some embar[r]assing questions: Has he ever read the Simula67
> 	Common Base standard? Simula BEGIN? What is Hash Consing and how
> 	does it relate to this discussion? What is rplac[ad] and how does
> 	it relate to this discussion?
> 
	This is an interesting idea: Usenet as an ongoing certification program,
or people's tribunal (``You don't even know the basics!'', shouts the Red
Guard to the Mandarin).  It is tempting to reply, as Mitterrand to
Giscard d'Estaing during the 1981 presidential debate,
``I am not your student, and you are not my professor'',
but let me not be stuffy and indeed answer.

	The author of Eiffel did write more than a few Lisp and Simula
programs, thank you. One of my first programming courses
was a Lisp course taught by Prof. John McCarthy; I remember him as
reasonably competent on the subject. On Simula, please see
``Quelques concepts importants des langages de programmation modernes,
et leur expression en Simula 67'', by the undersigned, GROPLAN 9, AFCET,
1979. (English version presented at the Tenth Conference of the
Association of Simula Users, Oslo, in, I believe, 1980 or 1981.)
As to rplaca and rplacd, the definition I am tempted to give is
``If you like the idea of functional programming, the main arguments
for using Miranda rather than Lisp''.

-- Bertrand Meyer
bertrand@eiffel.com