comp.lang.ada
 help / color / mirror / Atom feed
* Re: Choice of OO primitives in Ada95
  1996-02-19  0:00     ` Choice of OO primitives in Ada95 Don Harrison
@ 1996-02-19  0:00       ` Norman H. Cohen
  1996-02-19  0:00       ` Robert A Duff
  1996-02-21  0:00       ` Robert I. Eachus
  2 siblings, 0 replies; 35+ messages in thread
From: Norman H. Cohen @ 1996-02-19  0:00 UTC (permalink / raw)


In article <Dn0FqH.8Cw@assip.csasyd.oz>, donh@syd.csa.com.au (Don Harrison)
writes: 

|> I don't question the value of packages for non-OO encapsulation. I am interested
|> to know what is the perceived flexibility wrt OO. Did Tucker meant flexibility
|> wrt non-OO encapsulation?

I can't speak for Tucker, but my argument is as follows: 

      Packages, private parts, and package bodies are an appropriate
      mechanism for non-OO encapsulation that can be used in precisely
      the same way for OO encapsulation, equally appropriately.
      Therefore, a second, quite different mechanism for OO encapsulation
      would be redundant.

|> :2. It allows data abstractions involving two or more intimately linked
|> :   types to be encapsulated together.  For example: 
[my family-tree example deleted]
|>
|> This is an example of what I mean by tight-coupling of abstractions - you are
|> forced to encapsulate both abstractions into a single module.

No, I wasn't forced to do so, I chose to do so, because Marriage_Type and
Person_Type are part of a single recursive data structure and the
family-tree data abstraction has many operations that are most
efficiently implemented by referring to both the Marriage_Type and
Person_Type parts of this data structure.

Other applications entail mutually dependent types that are not
"initimately linked" in this way, and in such cases separate packages are
more appropriate.  A programmer whose encapsulation mechanism is a
package has the freedom to choose whether or not the two types should be
encapsulated together.  A programmer whose encapsulation mechanism is the
class does not.

|> :|> As far as symmetry between operands is concerned, the benefits seem to be more
|> :|> theoretical than practical.
|> : 
|> :The ability to use natural notation has the very practical advantage of
|> :making programs easier to read and understand.
|>
|> I would say the opposite is true - forcing a whole bunch of different abstractions
|> into the one module creates an amorphous mess that the developer has to sift
|> through to see which operations relate to which abstractions.

This is a non sequitur.  Your original remark about symmetry being of
only theoretical interest referred to the ability to define truly
symmetric binary dispatching operations.  I replied that this ability
provides a practical rather than theoretical advantage in terms of
program understandability.  You reply with a false and in any event
irrelevant suggestion that packages "force" different abstractions into
one module.

|> An example might best illustrate what I mean. Extending your example and assuming
|> each type is tagged, we might have: 
|>
|> package X is
|>   type MARRIAGE is tagged ...
|>   type PERSON is tagged ...
|>   type UNIVERSITY is tagged ...
|>   type GOVERNMENT is tagged ...
|>   type ELECTORATE is tagged ...
|>   type ADDRESS is tagged ...
|>
|>   procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY);
|>   procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY);
|>   procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE);
|>   function Office_Address (Elect : in ELECTORATE) return ADDRESS;
|>
|> end X;
|>
|> Each abstraction is related to the previous one but isn't necessarily related
|> to any other. As I understand it, the language rules dictate that each of these
|> abstractions must be in the same package.

You understand it incorrectly!

|>                                           But many of them have nothing to do with
|> each other. They are tightly-coupled even though they should be distinct and this
|> has been forced by the language rules.

There are several solutions for writing data abstractions that have
mutually dependent interfaces, but independent implementations, in
separate packages.  John Volan and I have debated two such approaches in
this newsgroup ad nauseum.

Ada packages give you the CHOICE of packaging two types together or
separately.  In the family-tree example, the two types are different
aspects of the same abstraction, with a shared implementation, and a
single package is appropriate.  (Other examples:  A package providing a
type for linked lists and a type for cursors representing positions in
linked lists; a package providing a type for points on a time line and a
type for lengths of intervals on a time line; a package providing a type
for machine addresses and a type for offsets between machine addresses;
a package providing a type for sparse matrices, a type identifying a row
of such a sparse matrix, and a type identifying a column of a sparse
matrix; etc.)

When it is not appropriate to package two mutually dependent types
together, Ada packages give you the CHOICE to encapsulate them
separately.

--
Norman H. Cohen    ncohen@watson.ibm.com




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-19  0:00     ` Choice of OO primitives in Ada95 Don Harrison
  1996-02-19  0:00       ` Norman H. Cohen
@ 1996-02-19  0:00       ` Robert A Duff
  1996-02-20  0:00         ` Don Harrison
  1996-02-21  0:00       ` Robert I. Eachus
  2 siblings, 1 reply; 35+ messages in thread
From: Robert A Duff @ 1996-02-19  0:00 UTC (permalink / raw)


In article <Dn0FqH.8Cw@assip.csasyd.oz>,
Don Harrison <donh@syd.csa.com.au> wrote:
>package X is
>  type MARRIAGE is tagged ...
>  type PERSON is tagged ...
>  type UNIVERSITY is tagged ...
>  type GOVERNMENT is tagged ...
>  type ELECTORATE is tagged ...
>  type ADDRESS is tagged ...
>
>  procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY);
>  procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY);
>  procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE);
>  function Office_Address (Elect : in ELECTORATE) return ADDRESS;
>
>end X;
>
>Each abstraction is related to the previous one but isn't necessarily related
>to any other. As I understand it, the language rules dictate that each of these 
>abstractions must be in the same package.

No, they don't have to be in the same package (and as you say, probably
should not be).  Could you explain what you mean -- why do you think
that all of the above types have to be in the same package?

(By the way, the above code is illegal, by 3.9.2(12).)

>I can't make any comment on C++ as I'm unfamiliar with it (must be the only
>one in the world). The Eiffel equivalent of static members are probably 'once'
>attributes which may optionally be exported (visible or private).

No, static members in C++ are not quite the same thing as Eiffel's
'once' attributes.  A static member is just a function that is inside
the class for visibility/encapsulation purposes, but isn't attached to
any particular object.  In other words, there's no "self" or "this" when
you call a static member.  A once attribute is a function that gets
executed just once, and the result gets saved -- when you call it again,
you get the saved value.  In Ada, you would just use a constant for that
purpose, in most cases.

>... This issue
>is language war flame bait and I don't intend to defend the pure OO position
>here :-)

Once attributes are flame bait?  Not sure why anybody would get too hot
about that issue.  OK, if you say so.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
       [not found]   ` <4g2f8v$15lc@watnews1.watson.ibm.com>
@ 1996-02-19  0:00     ` Don Harrison
  1996-02-19  0:00       ` Norman H. Cohen
                         ` (2 more replies)
  1996-02-21  0:00     ` John DiCamillo
  1 sibling, 3 replies; 35+ messages in thread
From: Don Harrison @ 1996-02-19  0:00 UTC (permalink / raw)


Norman H. Cohen) wrote:

:|In article <DMu9yw.5ts@assip.csasyd.oz>, donh@syd.csa.com.au (Don Harrison)
:|writes: 
:
:|> Tucker Taft wrote: 
:|>
:|> [...]
:|>
:|> : ...  The orthogonality of
:|> : types and modules in Ada 95 can be a major advantage,
:|> : gives the programmer more flexibility in structuring their system
:|>
:|> What flexibility does this approach offer over conventionally encapsulated classes?
:
:1. It allows other forms of encapsulation and packaging, not involving
:   classes.  We could have a package providing a nonextendible private
:   type for complex numbers, deferred constants zero, one, and i, and a
:   set of arithmetic operations.  We could have a package providing a set
:   of constants.  We could have a package providing a set of
:   higher-level auxiliary routines operating on a type provided by
:   another package, building on the primitive operations provided by that
:   package.  I've seen people try to use C++ classes with no nonstatic
:   members for these other forms of encapsulation and packaging, and the
:   result is strained.  That's one reason C++ has added namespaces, which
:   are like Ada packages.  But once the full generality of Ada-like
:   packages is available, the class program unit as an encapsulation
:   mechanism is redundant.

I don't question the value of packages for non-OO encapsulation. I am interested
to know what is the perceived flexibility wrt OO. Did Tucker meant flexibility
wrt non-OO encapsulation?

:2. It allows data abstractions involving two or more intimately linked
:   types to be encapsulated together.  For example: 
:
:   with Dates; use Dates;
:   package Family_Trees is
:
:      type Marriage_Type is private;
:      type Person_Type is private;
:
:      function New_Person
:         (Name       : String;
:          Birth_Date : Date_Type;
:          Death_Date : Date_Type := No_Date);
:
:      procedure Wed
:         (Husband       : in out Person_Type;
:          Wife          : in out Person_Type;
:          Marriage_Date : in Date_Type;
:          Divorce_Date  : in Date_Type := No_Date;
:          Marriage      : out Marriage_Type);
:
:      procedure Add_Offspring
:         (Marriage: in out Marriage_Type; Child: in out Person_Type);
:
:      function Husband (Marriage: in Marriage_Type) return Person_Type;
:      function Wife (Marriage: in Marriage_Type) return Person_Type;
:      function Marriage_Of (Spouse: in Person_Type) return Marriage_Type;
:      function Parents (Child: in Person_Type) return Marriage_Type;
:
:      generic
:         with procedure Process_One_Child (Child: in Person_Type);
:      procedure Process_All_Children (Marriage: in Marriage_Type);
:
:      generic
:         with procedure Process_One_Marriage (Marriage: in Marriage_Type);
:      procedure Process_All_Marriages (Spouse: in Person_Type);
:
:   private
:
:      ...
:
:   end Family_Trees;

This is an example of what I mean by tight-coupling of abstractions - you are
forced to encapsulate both abstractions into a single module.

:|> As far as symmetry between operands is concerned, the benefits seem to be more
:|> theoretical than practical.
:
:The ability to use natural notation has the very practical advantage of
:making programs easier to read and understand.

I would say the opposite is true - forcing a whole bunch of different abstractions
into the one module creates an amorphous mess that the developer has to sift
through to see which operations relate to which abstractions.

:|>                             Indeed, encapsulating classes has the practical
:|> advantage of cleaner interfaces to classes. Cleaner interfaces facilitate easier
:|> debugging, maintenance, reuse etc. The Ada 95 model works against this principle
:|> by forcing designers to create tightly-coupled classes because parts of their
:|> interfaces are shared.
:
:Ada does not "force" designers to do any such thing.  Indeed, the
:language encourages the use of encapsulated, loosely coupled data
:abstractions.

An example might best illustrate what I mean. Extending your example and assuming
each type is tagged, we might have:

package X is
  type MARRIAGE is tagged ...
  type PERSON is tagged ...
  type UNIVERSITY is tagged ...
  type GOVERNMENT is tagged ...
  type ELECTORATE is tagged ...
  type ADDRESS is tagged ...

  procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY);
  procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY);
  procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE);
  function Office_Address (Elect : in ELECTORATE) return ADDRESS;

end X;

Each abstraction is related to the previous one but isn't necessarily related
to any other. As I understand it, the language rules dictate that each of these 
abstractions must be in the same package. But many of them have nothing to do with
each other. They are tightly-coupled even though they should be distinct and this
has been forced by the language rules.

:|> Forcing ownership of operations by particular classes is entirely consistent with
:|> the pattern established in Ada 83 for packages: the components of a package OWN
:|> their components (attributes, operations, etc.). Therfore, mapping classes onto
:|> packages giving package classes follows quite naturally as shown by my model.
:
:Ada certainly recognizes a close relationship among packages, types, and
:operations:  If a package provides both a type and subprograms with
:parameters or results of that type, those subprograms "belong" to the
:type.  (In the technical jargon, they are "primitive operations" of the
:type.)
:
:But a package is a module, not a type.  The unnatural modeling of
:one-per-class data items as static "members" in C++ comes from an attempt
:to force-fit the two concepts into a single construct.  In Ada, a
:singleton data item is simply a variable declared inside a
:package--encapsulated in the package body if it is to be hidden (like a
:C++ private static data member).  There is no pretense that the variable
:is in any way a COMPONENT of any type that happens to be encapsulated in
:the same package as the variable.

I can't make any comment on C++ as I'm unfamiliar with it (must be the only
one in the world). The Eiffel equivalent of static members are probably 'once'
attributes which may optionally be exported (visible or private). This issue
is language war flame bait and I don't intend to defend the pure OO position
here :-)
 
:
:--
:Norman H. Cohen    ncohen@watson.ibm.com

Don.







^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-20  0:00         ` Don Harrison
@ 1996-02-20  0:00           ` Jon S Anthony
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
  1996-02-20  0:00           ` Choice of OO primitives in Ada95 Ray Toal
  1996-02-23  0:00           ` Robert A Duff
  2 siblings, 1 reply; 35+ messages in thread
From: Jon S Anthony @ 1996-02-20  0:00 UTC (permalink / raw)


In article <Dn22M0.G0D@assip.csasyd.oz> donh@syd.csa.com.au (Don Harrison) writes:
> Robert A Duff writes:
> 
> :In article <Dn0FqH.8Cw@assip.csasyd.oz>,
> :Don Harrison <donh@syd.csa.com.au> wrote:
> :>package X is
> :>  type MARRIAGE is tagged ...
> :>  type PERSON is tagged ...
> :>  type UNIVERSITY is tagged ...
> :>  type GOVERNMENT is tagged ...
> :>  type ELECTORATE is tagged ...
> :>  type ADDRESS is tagged ...
> :>
> :>...
> :>end X;
> :>

> :>Each abstraction is related to the previous one but isn't necessarily
> :>related to any other. As I understand it, the language rules dictate
> :>that each of these abstractions must be in the same package.
> :
> :No, they don't have to be in the same package (and as you say, probably
> :should not be).  Could you explain what you mean -- why do you think
> :that all of the above types have to be in the same package?
>
>  I don't have an RM available but quoting you (25.1.96) on the
> subject of dispatching operations in response to Arcadio A. Sincero:
> 
> > >As a matter of fact, the only indication that TPerson's Walk "belongs to
> > >it" is that TPerson's Walk has a TPerson parameter.
> 
> > That, plus the fact that it's in the same package.
> 
> So, if you want all of the operations to be dispatching (primitive), then the
> tagged types must also be in the same package.

What in this in anyway could even _possibly_ be construed in the
course of even the most tortuous path of illogic to be saying _all_
the types _together_ need to be in the _same_ package?  Hmmmmmm????


>  In the same thread, Jon S Anthony went on to say that
> non-dispatching operations using tagged types were those defined in
> different packages to those types:
> 
> > Just to add one more bit (completely beating it to death...), it is also
> > legal to have a subprogram with operands of both types as long as it is
> > not in the package where the two types are declared.  Of course such a
> > subprogram is not primitive and will never dispatch (assuming it has no
> > other controlling operands).

See above (possibly even more so).


>  Dispatching or not dispatching depending on where an operation is
> defined is not what you would call consistent.

Why not?  Seems pretty simple really.  And it allows for non
dispatching operations to be constructed if they have a closer match
to the desired semantics.  And why should operations that are closely
tied to the semantics of a type (basically the intent of primitive
operations) be definable anywhere?  That sort of thing leads pretty
quickly to inscrutable structures.  (I believe that Dylan does allow
this sort of thing, but there has been disagreement on how "wonderful"
it is.)


> A couple of other gripes:

>  1) Why should you have to specify that a type is 'tagged'? Can't
> the compiler work that out for itself? eg. by seeing whether the
> type is extended elsewhere. The developer is forced to worry about
> what should be an implementation issue.

Ahhh, the ol' clairvoyant compiler.  You are on a roll.  What if the
type is not extended?  This sort of comment might make sense if you
were discussing a language where the only kinds of types available
were "classes" (actually, it would not even make sense there as then
it would be irrelevant).  But you aren't.  Of course you can decry
this fact, but that is another matter altogether and irrelevant given
the current context.  Also, given the context, it is very much the
case that "tagged" is _not_ simply an implementation issue.  Flagging
a particular type as one which is extensible and supportive of dynamic
polymorphism can be argued to be a "good engineering" tradeoff.


> 2) Similarly, why should the developer have to specify that an
> operation dispatches (classwide operations)? Presumably, you're
> aiming for quicker execution, but compilers could perform a certain
> degree of optimisation eg. If it knows the type is not extended
> anywhere, there is no need to dispatch. There would also be
> situations where the specific variant of an inherited type is known
> eg. following an explicit assignment from an entity of that type.

This is just plain wrong - on several accounts.  First class wide
operations do not dispatch (they have uses more akin to a "generic
method" in CLOS, though clearly more restricted).  Second, _all_
primitive operations are dispatching operations.  The "developer" does
_not_ specify that an operation dispatches (other than simply
including it as a primitive operation of a tagged type).  Third,
optimization is irrelevant _to the semantics_ of whether any actual
_invocation_ dispatches.  Sans optimizations a primitive operation
dispatches iff it has class-wide actuals for the operation's
controlling parameters - the compiler _always_ knows when a particular
call of an operation dispatches.  Fourth, optimization is also
(mostly) irrelevant for making the design choice of keeping instances
of dynamic polymorphism a local rather than global issue.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
1 Williston Road, Suite 4
Belmont, MA 02178

617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-19  0:00       ` Robert A Duff
@ 1996-02-20  0:00         ` Don Harrison
  1996-02-20  0:00           ` Jon S Anthony
                             ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Don Harrison @ 1996-02-20  0:00 UTC (permalink / raw)


Robert A Duff writes:

:In article <Dn0FqH.8Cw@assip.csasyd.oz>,
:Don Harrison <donh@syd.csa.com.au> wrote:
:>package X is
:>  type MARRIAGE is tagged ...
:>  type PERSON is tagged ...
:>  type UNIVERSITY is tagged ...
:>  type GOVERNMENT is tagged ...
:>  type ELECTORATE is tagged ...
:>  type ADDRESS is tagged ...
:>
:>  procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY);
:>  procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY);
:>  procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE);
:>  function Office_Address (Elect : in ELECTORATE) return ADDRESS;
:>
:>end X;
:>
:>Each abstraction is related to the previous one but isn't necessarily related
:>to any other. As I understand it, the language rules dictate that each of these 
:>abstractions must be in the same package.
:
:No, they don't have to be in the same package (and as you say, probably
:should not be).  Could you explain what you mean -- why do you think
:that all of the above types have to be in the same package?

I don't have an RM available but quoting you (25.1.96) on the subject of dispatching
operations in response to Arcadio A. Sincero:

> >As a matter of fact, the only indication that TPerson's Walk "belongs to
> >it" is that TPerson's Walk has a TPerson parameter.

> That, plus the fact that it's in the same package.

So, if you want all of the operations to be dispatching (primitive), then the
tagged types must also be in the same package.

In the same thread, Jon S Anthony went on to say that non-dispatching operations
using tagged types were those defined in different packages to those types:

> Just to add one more bit (completely beating it to death...), it is also
> legal to have a subprogram with operands of both types as long as it is
> not in the package where the two types are declared.  Of course such a
> subprogram is not primitive and will never dispatch (assuming it has no
> other controlling operands).

Dispatching or not dispatching depending on where an operation is defined is not
what you would call consistent.

A couple of other gripes:

1) Why should you have to specify that a type is 'tagged'? Can't the compiler work
that out for itself? eg. by seeing whether the type is extended elsewhere. The
developer is forced to worry about what should be an implementation issue.

2) Similarly, why should the developer have to specify that an operation dispatches
(classwide operations)? Presumably, you're aiming for quicker execution, but
compilers could perform a certain degree of optimisation eg. If it knows the type
is not extended anywhere, there is no need to dispatch. There would also be
situations where the specific variant of an inherited type is known eg. following
an explicit assignment from an entity of that type.
 
[...]

:- Bob

Don.









^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-20  0:00         ` Don Harrison
  1996-02-20  0:00           ` Jon S Anthony
@ 1996-02-20  0:00           ` Ray Toal
  1996-02-21  0:00             ` Don Harrison
  1996-02-22  0:00             ` Bernd Holzmueller
  1996-02-23  0:00           ` Robert A Duff
  2 siblings, 2 replies; 35+ messages in thread
From: Ray Toal @ 1996-02-20  0:00 UTC (permalink / raw)


donh@syd.csa.com.au (Don Harrison) wrote:

>1) Why should you have to specify that a type is 'tagged'? Can't the compiler work
>that out for itself? eg. by seeing whether the type is extended elsewhere. The
>developer is forced to worry about what should be an implementation issue.

Requiring 'tagged' is a GOOD THING!  Inheritance weakens encapsulation.
The default case (no tagged) is that you design a type, and you
provide all and only those operations that work on the type and you
don't make any details available to anyone else - in short you
fully control the type.  Now if your intent is to ALLOW derivation
then you must mark it tagged.  This alerts the reader that this
type may be derived from.  Imagine a language in which you could
inherit from any type you wanted to! :-)  Whether or not a type
should be tagged is a DESIGN decision; I totally disagree that it
should be an implementation decision.  By the way a compiler can not
in general determine if the "type is extended elsewhere" since in
Ada extensions can appear in other compilation units.


>2) Similarly, why should the developer have to specify that an operation dispatches
>(classwide operations)? Presumably, you're aiming for quicker execution, but
>compilers could perform a certain degree of optimisation eg. If it knows the type
>is not extended anywhere, there is no need to dispatch. There would also be
>situations where the specific variant of an inherited type is known eg. following
>an explicit assignment from an entity of that type.

The reason you need to specify whether or not an operation dispatches
is that you can write code like

  procedure P (X: T) is begin R(X); end P;
  procedure Q (X: T'Class) is begin R(X); end Q;

which behave differently.

Ray Toal






^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-19  0:00     ` Choice of OO primitives in Ada95 Don Harrison
  1996-02-19  0:00       ` Norman H. Cohen
  1996-02-19  0:00       ` Robert A Duff
@ 1996-02-21  0:00       ` Robert I. Eachus
  2 siblings, 0 replies; 35+ messages in thread
From: Robert I. Eachus @ 1996-02-21  0:00 UTC (permalink / raw)



In article <Dn0FqH.8Cw@assip.csasyd.oz> donh@syd.csa.com.au (Don Harrison) writes:

  > This is an example of what I mean by tight-coupling of
  > abstractions - you are forced to encapsulate both abstractions
  > into a single module.

   Not FORCED to, choose to.

  > An example might best illustrate what I mean. Extending your
  > example and assuming each type is tagged, we might have:

  > package X is
  >   type MARRIAGE is tagged ...
  >   type PERSON is tagged ...
  >   type UNIVERSITY is tagged ...
  >   type GOVERNMENT is tagged ...
  >   type ELECTORATE is tagged ...
  >   type ADDRESS is tagged ...

  >    procedure Enrol (Student : in out PERSON; Uni : in out UNIVERSITY);
  >    procedure Award_Grant (Polies : in out GOVERNMENT; Uni : in out UNIVERSITY);
  >    procedure Make_Gerrymander (Polies : in out GOVERNMENT; Elect : in out ELECTORATE);
  >    function Office_Address (Elect : in ELECTORATE) return ADDRESS;

  > end X;

  > Each abstraction is related to the previous one but isn't
  > necessarily related to any other. As I understand it, the language
  > rules dictate that each of these abstractions must be in the same
  > package. But many of them have nothing to do with each other. They
  > are tightly-coupled even though they should be distinct and this
  > has been forced by the language rules.

    What language rules say this?  The only thing remotely close is
that when you have two types where you want primitive operations of
one with operands of the other, you have to chose one of several
approaches.  ONE of those approaches is to package the types together,
and if they are closely related, it is usually the right choice.
Other choices include using child packages, making the operations on
one type class-wide operations using a parent of the other type,
treating the relation between the two types as its own class,
generics, etc...

    But how would you attack this "problem" in C++?  The "solutions" I
have seen all have the same semantic effect as the Ada solution shown
even though the file layout is usually different.  (The mingling of
the types is via #includes.)

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
       [not found]   ` <4g2f8v$15lc@watnews1.watson.ibm.com>
  1996-02-19  0:00     ` Choice of OO primitives in Ada95 Don Harrison
@ 1996-02-21  0:00     ` John DiCamillo
  1996-02-22  0:00       ` Don Harrison
  1 sibling, 1 reply; 35+ messages in thread
From: John DiCamillo @ 1996-02-21  0:00 UTC (permalink / raw)


ncohen@watson.ibm.com (Norman H. Cohen) writes:
>|> Tucker Taft wrote: 
>|> : ...  The orthogonality of
>|> : types and modules in Ada 95 can be a major advantage,
>|> : gives the programmer more flexibility in structuring their system

But Cardelli and Wegner [CW85] showed that the opposite is
true: providing package types through existential quantification
is *more* flexible than having typeless package values as
Ada provides.  It also simplifies and unifies the concept of Ada
generic packages, which are almost package types, and allows
package values to be treated as first-class values.

To be sure, C&W based their analysis on a type system supporting
first class functional values (not present in Ada), so their
conclusions may not hold for Ada.  However, I find it difficult
to believe that the converse is actually true.

>|> What flexibility does this approach offer over conventionally encapsulated classes?

>1. It allows other forms of encapsulation and packaging, not involving
>   classes.  We could have a package providing a nonextendible private
>   type for complex numbers, deferred constants zero, one, and i, and a
>   set of arithmetic operations.  We could have a package providing a set
>   of constants.  We could have a package providing a set of
>   higher-level auxiliary routines operating on a type provided by
>   another package, building on the primitive operations provided by that
>   package.  I've seen people try to use C++ classes with no nonstatic
>   members for these other forms of encapsulation and packaging, and the
>   result is strained.

"Strained" in what way?  _D&E_ [Stroustrup94] mentions several
minor problems with this approach, but seems to be considering
using classes to wrap already existing global declarations.
(btw, i'm not disagreeing, just asking for clarification)

>   That's one reason C++ has added namespaces, which
>   are like Ada packages.

Sort of... Namespaces simply control name visibility, they are
not an abstraction mechanism.  Namespaces do not have private
parts.  Namespaces may be extended by multiple declarations.

>   But once the full generality of Ada-like
>   packages is available, the class program unit as an encapsulation
>   mechanism is redundant.

Again, sort of.  Why talk of adding a separate class program unit?
Why not just extend packages to provide package types?  That way,
you have only one mechanism for encapsulation (the package) and
packages become first class values, allowing for more flexible
package declarations and increased code-reuse.

[big snip]

>Ada certainly recognizes a close relationship among packages, types, and
>operations:  If a package provides both a type and subprograms with
>parameters or results of that type, those subprograms "belong" to the
>type.  (In the technical jargon, they are "primitive operations" of the
>type.)

>But a package is a module, not a type.

Which is the whole problem, despite what the rationale tries to
claim, IMHO.  Ada, despite being a very type-centric programming
language, has too limited a concept of types.

>The unnatural modeling of
>one-per-class data items as static "members" in C++ comes from an attempt
>to force-fit the two concepts into a single construct.

Not at all.  The unnatural modeling comes from a lack of class
values in C++.  This same problem causes the awkward semantics
of constructors and destructors.  In other words, static members
are a C++ problem, not a class problem.

>--
>Norman H. Cohen    ncohen@watson.ibm.com

-- 
    ciao,
    milo
================================================================
    John DiCamillo                         Fiery the Angels Fell 
    milod@netcom.com       Deep thunder rode around their shores




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-20  0:00           ` Choice of OO primitives in Ada95 Ray Toal
@ 1996-02-21  0:00             ` Don Harrison
  1996-02-23  0:00               ` Robert A Duff
  1996-02-22  0:00             ` Bernd Holzmueller
  1 sibling, 1 reply; 35+ messages in thread
From: Don Harrison @ 1996-02-21  0:00 UTC (permalink / raw)


Ray Toal wrote:

:donh@syd.csa.com.au (Don Harrison) wrote:
:
:>1) Why should you have to specify that a type is 'tagged'? Can't the compiler work
:>that out for itself? eg. by seeing whether the type is extended elsewhere. The
:>developer is forced to worry about what should be an implementation issue.
:
:Requiring 'tagged' is a GOOD THING!  Inheritance weakens encapsulation.

Not sure what you mean by this. Inheritance is no weaker or stronger in languages
(such as Eiffel) which map classes onto the encapsulation mechanism.

:The default case (no tagged) is that you design a type, and you
:provide all and only those operations that work on the type and you
:don't make any details available to anyone else - in short you
:fully control the type.  Now if your intent is to ALLOW derivation
:then you must mark it tagged.  This alerts the reader that this
:type may be derived from.  Imagine a language in which you could
:inherit from any type you wanted to! :-)

Yes, it's called Eiffel and it's great having such flexibility! :-). One aspect
of that flexibility is that, if, one sunny day, you decide you need to extend a
type you go right in and do it and don't have to touch the original. In Ada, you
have to go back and redefine the type to make it tagged. The impact of this may
be limited to that - don't know, haven't thought about it - but you shouldn't have
to redefine something to reuse it.

:                                            Whether or not a type
:should be tagged is a DESIGN decision; I totally disagree that it
:should be an implementation decision.  By the way a compiler can not
:in general determine if the "type is extended elsewhere" since in
:Ada extensions can appear in other compilation units.

I can't think offhand of a suitable way of dealing with this but that isn't to
say it's impossible. 

:>2) Similarly, why should the developer have to specify that an operation dispatches
:>(classwide operations)? Presumably, you're aiming for quicker execution, but
:>compilers could perform a certain degree of optimisation eg. If it knows the type
:>is not extended anywhere, there is no need to dispatch. There would also be
:>situations where the specific variant of an inherited type is known eg. following
:>an explicit assignment from an entity of that type.
:
:The reason you need to specify whether or not an operation dispatches
:is that you can write code like
:
:  procedure P (X: T) is begin R(X); end P;
:  procedure Q (X: T'Class) is begin R(X); end Q;
:
:which behave differently.

You don't have to do it that way. You can use (for example) a synonym construct like

  procedure P, Q (X: T) is begin R(X); end P, Q;

and redefine Q for extensions of X.

:
:Ray Toal
:
:

Don.









^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-20  0:00           ` Choice of OO primitives in Ada95 Ray Toal
  1996-02-21  0:00             ` Don Harrison
@ 1996-02-22  0:00             ` Bernd Holzmueller
  1996-02-23  0:00               ` Robert A Duff
  1 sibling, 1 reply; 35+ messages in thread
From: Bernd Holzmueller @ 1996-02-22  0:00 UTC (permalink / raw)


Ray Toal wrote:
> 
> donh@syd.csa.com.au (Don Harrison) wrote:
> 
> >1) Why should you have to specify that a type is 'tagged'? Can't the compiler work
> >that out for itself? eg. by seeing whether the type is extended elsewhere. The
> >developer is forced to worry about what should be an implementation issue.
> 
> Requiring 'tagged' is a GOOD THING!  Inheritance weakens encapsulation.
> The default case (no tagged) is that you design a type, and you
> provide all and only those operations that work on the type and you
> don't make any details available to anyone else - in short you
> fully control the type.  Now if your intent is to ALLOW derivation
> then you must mark it tagged.  This alerts the reader that this
> type may be derived from.  Imagine a language in which you could
> inherit from any type you wanted to! :-)  Whether or not a type
> should be tagged is a DESIGN decision; I totally disagree that it
> should be an implementation decision.  By the way a compiler can not
> in general determine if the "type is extended elsewhere" since in
> Ada extensions can appear in other compilation units.

Actually, the compiler _can_ work out if a tag is necessary. This is the case only if 
a type is used polymorphically, i.e., class-wide in Ada 95 terminology (and has 
_nothing_ to do with type-extension). A different implementation model than is given 
in the LRM would create a tag only in these cases, which would allow 'normal' 
(monomorphic) uses of a tagged type be as efficient as the use of an untagged type. 
The consequence is that a special kind of "tagged types" is not necessary if 
efficiency is of concern. This is discussed in more detail in a paper at Ada-Europe 96.

Regarding the requirement to mark a type tagged to control type extension: I cannot 
see any advantage in restricting the flexibility (in the sense of potential reuse) 
of the language without gaining anything. Whether or not a programmer is going to 
use a type for type extension is not relevant for the author of the original type 
and should therefore not explicitly prohibitable by him. It could be of interest 
for a _user_ of the original type because dispatching can be a concern, but not 
necessarily because he may wish to use this type only monomorphically, and thus 
no dispatching will ever occur.

Bernd

-- 
 -----------------------------------------------------------------------------
 Bernd Holzmueller,
 Institute of Computer Science, University of Stuttgart      
 email : holzmuel@informatik.uni-stuttgart.de
 http://www.informatik.uni-stuttgart.de/ifi/ps/bernd.html
 -----------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
  1996-02-22  0:00               ` Robert Dewar
@ 1996-02-22  0:00               ` Jon S Anthony
  1996-02-24  0:00               ` Valery Croizier
                                 ` (2 subsequent siblings)
  4 siblings, 0 replies; 35+ messages in thread
From: Jon S Anthony @ 1996-02-22  0:00 UTC (permalink / raw)


In article <dewar.824966245@schonberg> dewar@cs.nyu.edu (Robert Dewar) writes:

> Don says
> 
> "Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1)."
> 
> Well that's no more than an opinion, you provide no objective criterion to
> justify this opinion. In fact I think that Ada 95 satisfies 1) more
> convincingly than Eiffel. This has been discussed many times on this news
> group, and I don't particularly have anything to add to those previous
> discussions, I think it has all been said before!
> 
> The value of executable assertions has been hotly debated. To regard them
> as an essential part of OO programming seems odd to me, but of course
> people are free to say "x is essential for OO in my view" for almost
> any X (and all sorts of x's have been suggested). One trouble with
> executable assertions is that they are at the wrong level of abstraction,
> since they are confined to be at the semantic level of the language, and
> generally you want to talk about abstractions at a higher level.

Yes, Don says a lot of things.  He also says the following in
c.l.e:

<<<
Newsgroups: comp.lang.eiffel
Path: alexandria.organon.com!uunet!in2.uu.net!usc!howland.reston.ans.net!nntp.coast.net!harbinger.cc.monash.edu.au!news.mel.connect.com.au!news.syd.connect.com.au!warrane.connect.com.au!assip.csasyd!news
From: donh@syd.csa.com.au (Don Harrison)
Subject: Real OO
Message-ID: <Dn5sLw.A95@assip.csasyd.oz>
Sender: news@assip.csasyd.oz
Reply-To: donh@syd.csa.com.au
Organization: CSC Australia
Date: Thu, 22 Feb 1996 04:03:31 GMT
Lines: 11
 
For anyone interested, I've just stirred up the Ada nest with a posting 
titled 'Real OO'.
 
I didn't cross post it to here, for fear of boring you all with endless
follow-ups.
 
Regards,
Don.
>>>

Basically, he's just trolling.  So, it is best to not waste time
replying to anything he posts.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
1 Williston Road, Suite 4
Belmont, MA 02178

617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-21  0:00     ` John DiCamillo
@ 1996-02-22  0:00       ` Don Harrison
  1996-02-24  0:00         ` Robert A Duff
  0 siblings, 1 reply; 35+ messages in thread
From: Don Harrison @ 1996-02-22  0:00 UTC (permalink / raw)


John DiCamillo wrote:

[objective arguments about class encapsulation]

Thank you. I was beginning to wonder whether there was anyone else in this forum
willing to discard their preconceived ideas and able to think objectively on
this subject.

Don.


 







^ permalink raw reply	[flat|nested] 35+ messages in thread

* Real OO (was Choice of OO primitives in Ada95)
  1996-02-20  0:00           ` Jon S Anthony
@ 1996-02-22  0:00             ` Don Harrison
  1996-02-22  0:00               ` Robert Dewar
                                 ` (4 more replies)
  0 siblings, 5 replies; 35+ messages in thread
From: Don Harrison @ 1996-02-22  0:00 UTC (permalink / raw)



To Norman Cohen:

Thanks for giving the example about Family Trees.
I've gained access to an RM and Rationale. I'll go and check whether my
understanding is correct. (I was asking for trouble debating an issue without
the reference material handy).

To Jon Anthony:

On the necessity or otherwise of "tagged" and "'Class", I acknowledge that with
hybrid OO model adopted in Ada 95, it may be appropriate to require these of
developers - I'll reserve judgement until I've re-read the RM and Rationale.

---------------------------------------------------------------------------------
The real issue to me is that the Ada 95 OO model falls short of what real object-
orientation is about. The purpose of OO, as I see it is this:

"To enable the cost-effective development of correct, reliable and maintainable
 software".

The sub-goals required to facilitate this are:

a) Allow decomposition of the software into intelligible modules each of which
   represents a clearly defined abstraction and has a clearly defined interface
   with other abstractions

b) Allow the construction, where possible, of abstractions using abstractions
   that are already defined, customising them as necessary rather than
   defining abstractions from sctrach.

c) Allow the valid state of an abstraction to be clearly defined and enforced.

In order to acheive those goals optimally, an OO language should offer:

1) encapsulated abstractions (classes)
2) inheritance/polymorphism of those abstractions
3) control over the state of those abstractions (assertions).

Taking each in turn (and not attempting to justify them),

1) Best provided by pure OO (eg. Eiffel, Smalltalk) followed by hybrid OO
   language with proper classes (extendable types mapped onto modules)
   eg. (C++, myriad others) followed by hybrid OO with non-encapsulated classes
   (eg. Ada, CLOS?).

2) The linchpin of OO - any language claiming to be OO offers this.

3) The only significant OO language I know of that offers this is Eiffel.
   Assertions are executable conditions which must be satisfied to guarantee
   that an abstraction has a valid state whenever it is updated. These include:

   i)   pre-conditions on operations that callers are required to satisfy
   ii)  invariant conditions that must always be true when the abstraction is updated
   iii) post-conditions on operations stating what the abstraction guarantees to
        have done when the operation has been executed.

   There are others.

Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1).

While Eiffel is strong in the OO stakes (it satifies all 3), it is weak
(unfortunately) in the RT arena. These weaknesses are:

a) poor low level facilities (bit fiddling)
b) GC renders it an inappropriate tool for hard real-time systems (although the
   emergence of mainstream parallel architectures will permit this)
c) no concurrency (an elegant model currently being implemented - not yet part
   of the standard).

I think these will all be addressed in time but if none are a concern to you,
I suggest taking a look at Eiffel.

Don.









^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
@ 1996-02-22  0:00               ` Robert Dewar
  1996-02-23  0:00                 ` Gene Ouye
  1996-02-22  0:00               ` Jon S Anthony
                                 ` (3 subsequent siblings)
  4 siblings, 1 reply; 35+ messages in thread
From: Robert Dewar @ 1996-02-22  0:00 UTC (permalink / raw)


Don says

"Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1)."

Well that's no more than an opinion, you provide no objective criterion to
justify this opinion. In fact I think that Ada 95 satisfies 1) more
convincingly than Eiffel. This has been discussed many times on this news
group, and I don't particularly have anything to add to those previous
discussions, I think it has all been said before!

The value of executable assertions has been hotly debated. To regard them
as an essential part of OO programming seems odd to me, but of course
people are free to say "x is essential for OO in my view" for almost
any X (and all sorts of x's have been suggested). One trouble with
executable assertions is that they are at the wrong level of abstraction,
since they are confined to be at the semantic level of the language, and
generally you want to talk about abstractions at a higher level.





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 Real OO (was Choice of OO primitives in Ada95) Jean-Pierre Rosen
  1996-02-22  0:00 ` Spencer Allain
@ 1996-02-22  0:00 ` Matt Kennel
  1996-02-23  0:00   ` Robert A Duff
  1996-02-22  0:00 ` Valery Croizier
  1996-02-23  0:00 ` Jon S Anthony
  3 siblings, 1 reply; 35+ messages in thread
From: Matt Kennel @ 1996-02-22  0:00 UTC (permalink / raw)


Jean-Pierre Rosen (rosen@EMAIL.ENST.FR) wrote:
> >Taking each in turn (and not attempting to justify them),
> >
> >1) Best provided by pure OO (eg. Eiffel, Smalltalk) followed by hybrid OO
> >   language with proper classes (extendable types mapped onto modules)
> >   eg. (C++, myriad others) followed by hybrid OO with non-encapsulated classes
> >   (eg. Ada, CLOS?).
> Of course, I do not agree. For example, the presence of ONCE functions in
> Eiffel is a kludge to overcome the absence of package initialization that is
> nicely provided by Ada.

Um maaaaybe, but 'once functions' do what they do with no fuss and with
very clear semantics, without having to define an "elaboration" notion for
packages. 

I'm not sure that's a "kludge" compared to the complexity of package
initialization in Ada. 

>  And as for separating specs and implementations, Ada
> is the only language that does it nicely, without giving up safety.

This isn't true.

You write abstract classes in Eiffel/Sather/C++ which has the spec
(including pre/post/invariant) and write an implementation class which
supports it. 

What is the problem?

> >
> >2) The linchpin of OO - any language claiming to be OO offers this.
> Including Ada 95, although I still think it has been overadvocated.
> >
> >3) The only significant OO language I know of that offers this is Eiffel.
> >   Assertions are executable conditions which must be satisfied to guarantee
> >   that an abstraction has a valid state whenever it is updated. These include:
> > [...]
> It was considered in the early stages of Ada  (83) design, and rejected.
> Note also that assertions in Eiffel are much LESS reliable than one could
> think, since assertions are disabled while evaluation the condition for an
> assertion. This is necessary to prevent semantic dependencies to end up in
> infinite recursion, but limits the trust you can have in assertions.

No.  Meyer figured out, quite successfully IMHO, exactly the kinds of
rules that you need to turn "assertions" from just 'check this predicate
and bomb if false' into a powerful *human* protocol "programming by
contract". 

These special rules are exactly what you need so you CAN trust assertions,
because it means that you can put in truly useful checks that don't barf
because of stupidities like the above. 

> >
> >Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1).
> I have a package for 3) if you want. It's less than 50 lines long, including
> comments.

> So what ? Your statements were biased towards the conclusion that Eiffel was
> the only appropriate language. I can  come up with equally biased statements
> that will "naturally" conclude that Ada is the best OOP language. What
> about, for example:

>    OOP is about modelling real-world objects. Since real-world objects evolve
>    concurrently, no language should be called OO unless it provides concurrency.

> OK, this kills C++, Smalltalk, Eiffel, CLOS....

     OOP is about modelling real-world objects. Since real world objects couple
     to the Einstein mass-energy tensor, no langauge should be called OO unless
     its operation can provide sufficient extra energy dissipation to cause 
     similar effects.

:-) 


I think it *is* quite fair to say that Eiffel is more object-oriented---ok
more oriented-around-objects than Ada 95: it's the idee' fixe for Eiffel. 

This doesn't prove 'prima facie' superiority, though I tend to like
Eiffel better.  (I've never been convinced about kludges to handle the 
'multiple withing' problem).


> +------------------------------------o-------------------------------------+
> | P-mail:                            | E-mail: rosen@enst.fr               |
> |   ADALOG - 27 avenue de Verdun     |    Tel: +33 1 46 45 51 12           |
> |   92170 Vanves - FRANCE            |    Fax: +33 1 46 45 52 49           |
> +------------------------------------o-------------------------------------+




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
@ 1996-02-22  0:00 Jean-Pierre Rosen
  1996-02-22  0:00 ` Spencer Allain
                   ` (3 more replies)
  0 siblings, 4 replies; 35+ messages in thread
From: Jean-Pierre Rosen @ 1996-02-22  0:00 UTC (permalink / raw)


At 03:17 22/02/1996 GMT, Don Harrison wrote:
This time I can't  resist responding.... Here we go:

>The real issue to me is that the Ada 95 OO model falls short of what real
>object-
>orientation is about. The purpose of OO, as I see it is this:
>
>"To enable the cost-effective development of correct, reliable and maintainable
> software".
Agreed.

>The sub-goals required to facilitate this are:
>a) Allow decomposition of the software into intelligible modules each of which
>   represents a clearly defined abstraction and has a clearly defined interface
>   with other abstractions
>
>b) Allow the construction, where possible, of abstractions using abstractions
>   that are already defined, customising them as necessary rather than
>   defining abstractions from sctrach.
>
>c) Allow the valid state of an abstraction to be clearly defined and enforced.
Are you sure these are the best sub-goals ? That there are no other ones ?
And that in  stating the goals, you were not influenced by the conclusion
you wanted to draw ? But let's go with it for the moment.

>In order to acheive those goals optimally, an OO language should offer:
>
>1) encapsulated abstractions (classes)
OK, but of course you mean that there must be a clear separation, at
language level, between specification and implementation

>2) inheritance/polymorphism of those abstractions
How  can you deduce this from b) ? Inheritance is definitely one possible
way, but you are claiming here it is the only one. I think building an
abstraction by putting together standardized, appropriate building blocks
and lower level abstractions is another way of achieving b) that does not
require inheritance.
Both approaches have benefits and drawbacks. I'm just irritated each time I
see that because inheritance is one way of solving a problem, people think
it is the only one.

>3) control over the state of those abstractions (assertions).
I think a typing system that does not allow  adding a length to a velocity
is much more important for c) than assertions that are nothing more that a
user definable function call.
>
>Taking each in turn (and not attempting to justify them),
>
>1) Best provided by pure OO (eg. Eiffel, Smalltalk) followed by hybrid OO
>   language with proper classes (extendable types mapped onto modules)
>   eg. (C++, myriad others) followed by hybrid OO with non-encapsulated classes
>   (eg. Ada, CLOS?).
Of course, I do not agree. For example, the presence of ONCE functions in
Eiffel is a kludge to overcome the absence of package initialization that is
nicely provided by Ada. And as for separating specs and implementations, Ada
is the only language that does it nicely, without giving up safety.
>
>2) The linchpin of OO - any language claiming to be OO offers this.
Including Ada 95, although I still think it has been overadvocated.
>
>3) The only significant OO language I know of that offers this is Eiffel.
>   Assertions are executable conditions which must be satisfied to guarantee
>   that an abstraction has a valid state whenever it is updated. These include:
> [...]
It was considered in the early stages of Ada  (83) design, and rejected.
Note also that assertions in Eiffel are much LESS reliable than one could
think, since assertions are disabled while evaluation the condition for an
assertion. This is necessary to prevent semantic dependencies to end up in
infinite recursion, but limits the trust you can have in assertions.

>
>Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1).
I have a package for 3) if you want. It's less than 50 lines long, including
comments.

So what ? Your statements were biased towards the conclusion that Eiffel was
the only appropriate language. I can  come up with equally biased statements
that will "naturally" conclude that Ada is the best OOP language. What
about, for example:

   OOP is about modelling real-world objects. Since real-world objects evolve
   concurrently, no language should be called OO unless it provides concurrency.

OK, this kills C++, Smalltalk, Eiffel, CLOS....
+------------------------------------o-------------------------------------+
| P-mail:                            | E-mail: rosen@enst.fr               |
|   ADALOG - 27 avenue de Verdun     |    Tel: +33 1 46 45 51 12           |
|   92170 Vanves - FRANCE            |    Fax: +33 1 46 45 52 49           |
+------------------------------------o-------------------------------------+




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 Real OO (was Choice of OO primitives in Ada95) Jean-Pierre Rosen
  1996-02-22  0:00 ` Spencer Allain
  1996-02-22  0:00 ` Matt Kennel
@ 1996-02-22  0:00 ` Valery Croizier
  1996-02-24  0:00   ` Robert A Duff
  1996-02-23  0:00 ` Jon S Anthony
  3 siblings, 1 reply; 35+ messages in thread
From: Valery Croizier @ 1996-02-22  0:00 UTC (permalink / raw)


In article <199602221711.SAA18350@email.enst.fr> Jean-Pierre Rosen <rosen@EMAIL.ENST.FR> writes:

> >3) The only significant OO language I know of that offers this is Eiffel.
> >   Assertions are executable conditions which must be satisfied to guarantee
> >   that an abstraction has a valid state whenever it is updated. These include:

> I have a package for 3) if you want. It's less than 50 lines long, including
> comments.

If you can simulate Eiffel-like assertions in a trivial way, then
please show it. I know how to check arguments and raise an exception,
but not so that these checkings are inherited by children, like in Eiffel. 

--
Valery CROIZIER
Valery.Croizier@enst-bretagne.fr




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 Real OO (was Choice of OO primitives in Ada95) Jean-Pierre Rosen
@ 1996-02-22  0:00 ` Spencer Allain
  1996-02-22  0:00 ` Matt Kennel
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 35+ messages in thread
From: Spencer Allain @ 1996-02-22  0:00 UTC (permalink / raw)


In article <199602221711.SAA18350@email.enst.fr> Jean-Pierre Rosen <rosen@EMAIL.ENST.FR> writes:

   >In order to acheive those goals optimally, an OO language should offer:
   >
   >1) encapsulated abstractions (classes)
   OK, but of course you mean that there must be a clear separation, at
   language level, between specification and implementation

<snip>

   >Taking each in turn (and not attempting to justify them),
   >
   >1) Best provided by pure OO (eg. Eiffel, Smalltalk) followed by hybrid OO
   >   language with proper classes (extendable types mapped onto modules)
   >   eg. (C++, myriad others) followed by hybrid OO with non-encapsulated classes
   >   (eg. Ada, CLOS?).
   Of course, I do not agree. For example, the presence of ONCE functions in
   Eiffel is a kludge to overcome the absence of package initialization that is
   nicely provided by Ada. And as for separating specs and implementations, Ada
   is the only language that does it nicely, without giving up safety.


Uhhh... since when has "encapsulated abstractions" been defined as limited 
to classes?  "Classes" are a way to encapsulate all the operations that are
associated with an object type.  "Interfaces" (where classes are really a
more restricted form of these) encapsulate all the operations that are
associated with the types visible to that specification -- there isn't
the single type restriction.

I also obviously do not agree with the explanation for (1), but I also
have to disagree with the statement that Ada is the only language that
separates specifications from their implementations, in a nice and
safe manner.  Modula-3 has a similar interface/implementation
separation, which is just as nice and equally as safe.  (It actually
resolves other safety issues not related to pure OO programming, but
that isn't what is being discussed here)

I think Ada has a powerful encapsulation system, but it is not the
only language with one.

-Spencer

----------------------------------------------------------------------
Spencer Allain                    E-mail:  spencer@era.com
Engineering Research Associates   Phone :  (703) 734-8800 x1414
1595 Spring Hill Road             Fax   :  (703) 827-9411
Vienna, VA  22182-2235

Ask me why _NOT_ to buy anything from Royal Prestige, a Hycite Co.
----------------------------------------------------------------------
<A HREF=http://www.research.digital.com/SRC/modula-3/html/home.html>
             Modula-3 Home Page DEC SRC</A>
<A HREF=http://www.vlsi.polymtl.ca/m3/>Modula-3 FAQ, etc. </A>
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-20  0:00         ` Don Harrison
  1996-02-20  0:00           ` Jon S Anthony
  1996-02-20  0:00           ` Choice of OO primitives in Ada95 Ray Toal
@ 1996-02-23  0:00           ` Robert A Duff
  2 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-23  0:00 UTC (permalink / raw)


In article <Dn22M0.G0D@assip.csasyd.oz>,
Don Harrison <donh@syd.csa.com.au> wrote:
>Robert A Duff writes:
>:No, they don't have to be in the same package (and as you say, probably
>:should not be).  Could you explain what you mean -- why do you think
>:that all of the above types have to be in the same package?
>
>I don't have an RM available but quoting you (25.1.96) on the subject of dispatching
>operations in response to Arcadio A. Sincero:
>
>> >As a matter of fact, the only indication that TPerson's Walk "belongs to
>> >it" is that TPerson's Walk has a TPerson parameter.
>
>> That, plus the fact that it's in the same package.
>
>So, if you want all of the operations to be dispatching (primitive), then the
>tagged types must also be in the same package.

Sorry, you misunderstood me.  In Ada, a procedure can only be
dispatching on *one* type.  It can have several parameters of that type,
and a result of that type (if it's a function).  But there is a run-time
check that all of those parameters have the same type tag.  Ada does not
have multi-dispatching, like CLOS does.  But neither to any of the
languages (such as Eiffel) that use the prefix notation.

Now a procedure that's dispatching on type T can have other parameters
of other types.  It does not need to be in the same package as those
other types.  Same thing in Eiffel -- the operation is inside one class,
and is dispatching (only) on that class, but can have parameters of some
other class.

So, typically, you put exactly one type in a package, and put its
primitive (dispatching) operations in that same package.  You can put
operations that don't dispatch on that type in some other package.

The one case where this doesn't work too well is when you have two types
that are defined in terms of each other (e.g. T1 contains a pointer to
T2, and T2 contains a pointer to T1).  When this happens, you are forced
to put both types in the same package, or use one of the slightly ugly
workarounds that have been discussed here recently.  I admit that is a
language design flaw.  But don't generalize that to say that all types
in your entire program have to get sucked into the same package!

>In the same thread, Jon S Anthony went on to say that non-dispatching operations
>using tagged types were those defined in different packages to those types:
>
>> Just to add one more bit (completely beating it to death...), it is also
>> legal to have a subprogram with operands of both types as long as it is
>> not in the package where the two types are declared.  Of course such a
>> subprogram is not primitive and will never dispatch (assuming it has no
>> other controlling operands).
>
>Dispatching or not dispatching depending on where an operation is defined is not
>what you would call consistent.

Heh?  I thought you were arguing in favor of the class-based languages,
which do exactly that.  In Eiffel, an operation is dispatching based on
which class it's in.

In CLOS, you can have dispatching operations that are declared whereever
you want.  That can lead to some rather disorganized code, but I suppose
it's necessary if you're going to have multi-methods.  Anyway, I think
it's best to gather the dispatching operations together with the type
(either inside it, as in Eiffel, or in the same package, as in Ada).

Note also that in Eiffel you can declare that a given operation cannot
be further overridden ("frozen", or something like that?).  That's a
very similar feature to what you complain about here -- in part, it is a
hint to the compiler that calling that function won't dispatch to
someplace else, and in part, it's a help in understanding the program,
because you can know exactly which function is being called.

>A couple of other gripes:
>
>1) Why should you have to specify that a type is 'tagged'? Can't the compiler work
>that out for itself? eg. by seeing whether the type is extended elsewhere. The
>developer is forced to worry about what should be an implementation issue.

No, the compiler cannot tell, because of separate compilation.  It can't
tell in the Eiffel case, either, for the same reason.  But in Eiffel,
everything's dispatching.  If you're willing to do extra work at link
time, then you can optimize away the tag field.  But not at compile
time.

Note that C++ has essentially the same thing -- the "virtual" keyword.
If there are no virtual functions in a class, then no tag field is
necessary.  In Ada, if there is no "tagged" keyword, then no tag field
is necessary.  (One difference between Ada and C++ is that in Ada you
cannot extend an untagged type with extra record components, whereas as
you *can* do that in C++ (i.e. you can extend a class that has no
virtual functions.  There was a big fight about that during the design
of Ada 9X.  I don't like the way it turned out).

So, you're pretty much correct that "tagged" is not a logical necessity.
It is, in fact, an efficiency hack.

>2) Similarly, why should the developer have to specify that an operation dispatches
>(classwide operations)? Presumably, you're aiming for quicker execution, but
>compilers could perform a certain degree of optimisation eg. If it knows the type
>is not extended anywhere, there is no need to dispatch. There would also be
>situations where the specific variant of an inherited type is known eg. following
>an explicit assignment from an entity of that type.

The reason for this is to avoid what is sometimes called the "fragile
base class" problem that occurs in many large OO programs.  If
*everything* is potentially dispatching, it's much harder to understand
the program.  Better to do something special if you want dispatching.

Another reason is of course upward compatibility.  Ada 83 subprograms
did not do dispatching, and of course you don't want all your Ada 83
programs to drastically change their behavior when compiled by an Ada 95
compiler.

I suppose quicker execution is part of the reason, but it's not the main
thing.

Another point about the design of Ada's OOP: It was essential that there
be little or no distributed overhead.  That is, if you don't use the
feature, your program should not be slowed down by the mere existence of
the feature.  And if you recompile an Ada 83 program with an Ada 95
compiler, it shouldn't get slower (assuming the Ada 95 compiler is as
high quality as the Ada 83 one).  If dispatching always happened, there
would be distributed overhead (both space and time), that could not be
eliminated without link-time optimizations.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-21  0:00             ` Don Harrison
@ 1996-02-23  0:00               ` Robert A Duff
  0 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-23  0:00 UTC (permalink / raw)


In article <Dn42C3.21u@assip.csasyd.oz>,
Don Harrison <donh@syd.csa.com.au> wrote:
>Ray Toal wrote:
>:Requiring 'tagged' is a GOOD THING!  Inheritance weakens encapsulation.
>
>Not sure what you mean by this. Inheritance is no weaker or stronger in languages
>(such as Eiffel) which map classes onto the encapsulation mechanism.

He didn't say "inheritance" is weaker, he said "encapsulation" is
weaker.  That's clearly true -- when you see a function call that cannot
dispatch, you know for sure exactly what it does.  When you see a
dispatching call, it might go off and do something you've never heard
of.  If there's no dispatching, then a single abstraction is completely
encapsulated, whereas with dispatching, an overriding function can sneak
in and do buggy things.  Dispatching is a powerful feature, but it has
this cost.  If you use dispatching when you don't need it, you are
paying that cost without getting any benefit.  Therefore, it makes sense
to give the programmer the choice.  Note that Eiffel seems to agree with
this, to some extent -- otherwise, the "frozen" (or whatever it's
called) thing wouldn't exist.

Of course, the counter-argument is that you don't always know ahead of
time when you might need dispatching.

I'm not sure I agree with Ray Toal, though, that requiring "tagged" is a
Good Thing.  Even without that rule, Ada still gives you control over
whether things dispatch, on a call-by-call basis.  So, I view "tagged"
as simply an efficiency hack.  Efficiency is a Good Thing, too, though.

>Yes, it's called Eiffel and it's great having such flexibility! :-). One aspect
>of that flexibility is that, if, one sunny day, you decide you need to extend a
>type you go right in and do it and don't have to touch the original.

Well, that's not *really* true.  You quite often have to go back and
change the original, because you're doing something new that conflicts
with assumptions made by the original.

>... In Ada, you
>have to go back and redefine the type to make it tagged. The impact of this may
>be limited to that - don't know, haven't thought about it - but you shouldn't have
>to redefine something to reuse it.

I pretty much agree with that.  You can, of course, make all your types
tagged in the first place, and then you won't have that problem.

>:                                            Whether or not a type
>:should be tagged is a DESIGN decision; I totally disagree that it
>:should be an implementation decision.  By the way a compiler can not
>:in general determine if the "type is extended elsewhere" since in
>:Ada extensions can appear in other compilation units.
>
>I can't think offhand of a suitable way of dealing with this but that isn't to
>say it's impossible. 

It is clearly possible to do at link time, and clearly impossible at
compile time, given separate compilation.

>You don't have to do it that way. You can use (for example) a synonym construct like
>
>  procedure P, Q (X: T) is begin R(X); end P, Q;
>
>and redefine Q for extensions of X.

Yes, that's another reasonable way to do it.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-22  0:00             ` Bernd Holzmueller
@ 1996-02-23  0:00               ` Robert A Duff
  0 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-23  0:00 UTC (permalink / raw)


In article <312C236B.2344@informatik.uni-stuttgart.de>,
Bernd Holzmueller  <holzmuel@informatik.uni-stuttgart.de> wrote:
>Actually, the compiler _can_ work out if a tag is necessary. ...

Are you saying that if I have a program that contains no dispatching at
all (i.e. nothing is ever converted to a class-wide type), then it is
possible for the compiler to avoid ever storing tags?  I don't see how
that can be true, because of re-dispatching.  Consider:

    package P1 is
       type T1 is tagged null record;
       procedure P(X: T1);
       procedure Q(X: T1);
    end P1;

    with P1; use P1;
    package P2 is
       type T2 is new T1 with null record;
       -- Override Q, but not P:
       procedure Q(X: T2);
    end P2;

    with P1; use P1;
    with P2; use P2;
    procedure Client is
       Object: T2;
    begin
       P(T1(X)); -- This is *not* a dispatching call.
    end Client;

I claim that the tag of Object (namely the tag representing type T2)
must be made available to procedure P1.P.  The tag could be stored as a
hidden component of Object, or it could be passed as an extra parameter
to P.  Either way, there is some overhead in doing this.  Now, suppose
there's no dispatching anywhere in the program.  For example, P might
look like this:

    procedure P(X: T1) is
    begin
       Q(X); -- This is *not* a dispatching call.
    end P;

Then we've wasted some time and space by making that tag available to P.
Distributed overhead.

So, what if we eliminate that tag?  Well, then if P looks like this:

    procedure P(X: T1) is
    begin
       Q(T1'Class(X)); -- This *is* a dispatching call.
    end P;

it won't work, because the above call is supposed to call the version of
Q for T2.

But the compiler cannot know, at compile time of Client, what the body
of P looks like.  Therefore, it *must* pass that information to P, just
*in case* P does a dispatching call.

QED.

Unless, of course, you're willing to generate code at link time.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00               ` Robert Dewar
@ 1996-02-23  0:00                 ` Gene Ouye
  1996-02-26  0:00                   ` James O'Connor
  0 siblings, 1 reply; 35+ messages in thread
From: Gene Ouye @ 1996-02-23  0:00 UTC (permalink / raw)



You realize, of course, that to the outside world (more 
specifically, to many that I know in the C++ community), 
watching this arguing between Eiffel and Ada advocates is 
like watching two hyenas fighting over the last scraps of 
a carcass after the pride of lions has had its fill...

You also realize, of course, that I'm not trying to say 
that any of this discussion is futile (if I ever find that 
to be true, I will be very depressed!).

Gene Ouye <geneo@rational.com>





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 Real OO (was Choice of OO primitives in Ada95) Jean-Pierre Rosen
                   ` (2 preceding siblings ...)
  1996-02-22  0:00 ` Valery Croizier
@ 1996-02-23  0:00 ` Jon S Anthony
  3 siblings, 0 replies; 35+ messages in thread
From: Jon S Anthony @ 1996-02-23  0:00 UTC (permalink / raw)


In article <4git9e$cqi@stc06.ctd.ornl.gov> kennel@msr.epm.ornl.gov (Matt Kennel) writes:

> > Of course, I do not agree. For example, the presence of ONCE functions in
> > Eiffel is a kludge to overcome the absence of package initialization that
> > is nicely provided by Ada.
> 
> Um maaaaybe, but 'once functions' do what they do with no fuss and with
> very clear semantics, without having to define an "elaboration" notion for
> packages. 
> 
> I'm not sure that's a "kludge" compared to the complexity of package
> initialization in Ada. 

I would agree that "once functions" make sense in the Eiffel design
pattern and are not really a kludge.  Ada elaboration, of course, fits
its design pattern.  In this particular case, there really isn't much
difference between them in the effects that can be accomplished.  Ada
elaboration provides for a few more things but that is more due to the
fact that packages are not types.


> >  And as for separating specs and implementations, Ada
> > is the only language that does it nicely, without giving up safety.
> 
> This isn't true.

Correct, M3 (and M2) for example provide this as well.


> You write abstract classes in Eiffel/Sather/C++ which has the spec
> (including pre/post/invariant) and write an implementation class which
> supports it. 
> 
> What is the problem?

I don't know.  But it is not the same.  You still have the interface
of the so called "implementation" class which is inextricably hooked
to _its_ implementation.  The fact is that Meyer (for various reasons)
decided _against_ separation of interface and implementation.  So, if
you are going to argue about this, you should be arguing about whether
this choice was "a good idea" (and not pretending that it isn't true).


> No.  Meyer figured out, quite successfully IMHO, exactly the kinds of
> rules that you need to turn "assertions" from just 'check this predicate
> and bomb if false' into a powerful *human* protocol "programming by
> contract". 

Well, more or less.  To me the real important thing about Eiffel
assertions is that they "go in the right place".  For example, it
is up to the client (enforced via assertions) that the pre-conditions
of a "server" are satisfied.


> These special rules are exactly what you need so you CAN trust assertions,
> because it means that you can put in truly useful checks that don't barf
> because of stupidities like the above. 

Well, more or less.


> I think it *is* quite fair to say that Eiffel is more object-oriented---ok
> more oriented-around-objects than Ada 95: it's the idee' fixe for Eiffel. 

From the standpoint of the 'everything is an "object"'
fanat-ahhh-ideology this is clearly true.  Actually, it is even more
specific than this, viz, all the world's a class.  I'm not
particularly enamored of this point of view.  For one thing it is not
obvious what the statement even says, if for no other reason than the
fact the central concept is so ill defined as to be meaningless.  Of
course, this sort of fact has never bothered programmers before - and
probably never will.


> This doesn't prove 'prima facie' superiority, though I tend to like
> Eiffel better.  (I've never been convinced about kludges to handle the 
> 'multiple withing' problem).

Check.  As for the "withing" problem, well it is clearly an easy and
legitimate target.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
1 Williston Road, Suite 4
Belmont, MA 02178

617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 ` Matt Kennel
@ 1996-02-23  0:00   ` Robert A Duff
  0 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-23  0:00 UTC (permalink / raw)


In article <4git9e$cqi@stc06.ctd.ornl.gov>,
Matt Kennel <kennel@msr.epm.ornl.gov> wrote:
>Um maaaaybe, but 'once functions' do what they do with no fuss and with
>very clear semantics, without having to define an "elaboration" notion for
>packages. 
>
>I'm not sure that's a "kludge" compared to the complexity of package
>initialization in Ada. 

I'd say both mechanisms leave something to be desired.

>I think it *is* quite fair to say that Eiffel is more object-oriented---ok
>more oriented-around-objects than Ada 95: it's the idee' fixe for Eiffel. 

Yes, of course Eiffel is more object oriented than Ada.  (Not sure why
you add "-around-objects".)  This is because Ada has many features that
are not object-oriented at all.  There's no support, for example, for
polymorphic operations on tasks or arrays.  But this has nothing to do
with the package-vs-class issue.  The features of Ada that *do* support
OOP are just as OOP as anything else.

>This doesn't prove 'prima facie' superiority, though I tend to like
>Eiffel better.  (I've never been convinced about kludges to handle the 
>'multiple withing' problem).

What is the "multiple withing" problem?

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
                                 ` (2 preceding siblings ...)
  1996-02-24  0:00               ` Valery Croizier
@ 1996-02-24  0:00               ` Robert A Duff
  1996-02-26  0:00                 ` Matthew B. Kennel
  1996-02-26  0:00                 ` Don Harrison
  1996-02-26  0:00               ` So called Real OO (was blah blah blah...) Jon S Anthony
  4 siblings, 2 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-24  0:00 UTC (permalink / raw)


In article <Dn5qGH.9xH@assip.csasyd.oz>,
Don Harrison <donh@syd.csa.com.au> wrote:
>... (I was asking for trouble debating an issue without
>the reference material handy).

:-) :-) :-) 

>Note that Ada only fully satisfies 2) and has a sub-optimal mechanism for 1).

You've said elsewhere that you don't like Ada's support for 1).  I
suppose it's something of a matter of taste.  I happen to think that
Ada's support for 1) is *better* than Eiffel, and the other languages
that combine Ada's notion of package and type into one.

You seemed to object strongly to the idea that one can put two types in
the same package, on the grounds that it decreases encapsulation.  On
the contrary, it *increases* encapsulation.  When two types are closely
related to each other, by their nature, *forcing* them to be in separate
modules means that *more* operations need to be exported from each
module.

Encapsulation isn't some sort of Goodness, such that the more you have
of it, the better.  No, you want to encapsulate things at the "right"
level of granularity for the problem at hand.  Usually, that's a single
type, plus the operations belonging to that type.  However, in some
cases, two types are so closely related that the right granularity is to
put them both in the same package.  (After all, in Fortran 66, the only
module is the subroutine, which is a *smaller* granularity than the
class.  But that doesn't make the encapsulation better.)

An example is a List type, plus a List_Cursor type.  The List_Cursor
points at a certain place in the list, and has operations for moving
forward and/or backward and so forth.  These operations cannot be
written without visibility on implementation details of *both* types.
So if class=module, you have to *export* a lot of those implemenation
details from one of them, so the other one can do what it needs to do.
Putting them both in the same module, however, actually gives you
*better* encapsulation, because fewer (and higher-level) operations get
exported.

Last time I looked at Eiffel, the standard library classes put the
cursor movement stuff inside the list.  That seems like a poor design,
since you can only be looping through a given list once, at any given
time.  It seems to me that you badly want the List_Cursor type to be
separate from the List type, although they *are* part of the same
"module".

>While Eiffel is strong in the OO stakes (it satifies all 3), 

I agree that Eiffel is superior to Ada with respect to your number 3) --
that is, the assertion stuff.  Ada does have *some* support for
assertions.  For example, if I say, "type T is range 1..10;", then
there's an invariant on T -- all objects of type T have to be in the
range 1 to 10.  This is pretty weak, compared to Eiffel, though.

I think it's silly to call that part of OO, though.  It's a completely
orthogonal issue.  Assertions would be useful in a non-OO language, too.

If you define "OO" as being "anything I happen to think is good", then
the term becomes useless, and people end up arguing about how, "My Daddy
is more OO than your Daddy."

Meyer also said that garbage collection is a fundamental part of OO.
Nonsense.  GC existed before OO, and it's not necessary in order to
support the real fundamentals of OO, such as polymorphism.

Why not just say that GC is a Good Thing, or assertions are a Good
Thing, or Eiffel's assertions are better than Ada's assertions, or C++
sucks because it makes it hard to implement GC?  It's silly to use the
term "OO" as a synonym for "the set of all Good Things".

>...it is weak
>(unfortunately) in the RT arena. These weaknesses are:
>
>a) poor low level facilities (bit fiddling)
>b) GC renders it an inappropriate tool for hard real-time systems (although the
>   emergence of mainstream parallel architectures will permit this)

Some people believe quite strongly that GC is appropriate for hard
real-time systems.  But that's another thread.

>c) no concurrency (an elegant model currently being implemented - not yet part
>   of the standard).

So I've heard.  How does this new elegant model deal with the issue I
mentioned above, about putting list-cursor information inside the list
itself?  If you have multiple tasks, you definitely want to have two
tasks iterating through the same shared list (or whatever data
structure).  Has the standard class library been changed to solve this
problem?

>I think these will all be addressed in time but if none are a concern to you,
>I suggest taking a look at Eiffel.

Indeed.  Even if they *are* a concern, it's still instructive to learn
Eiffel, and to read Meyer's classic book on OOP.  Programming by
contract is a useful concept in any language.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Choice of OO primitives in Ada95
  1996-02-22  0:00       ` Don Harrison
@ 1996-02-24  0:00         ` Robert A Duff
  0 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-24  0:00 UTC (permalink / raw)


In article <Dn5K6K.8zI@assip.csasyd.oz>,
Don Harrison <donh@syd.csa.com.au> wrote:
>John DiCamillo wrote:
>
>[objective arguments about class encapsulation]
>
>Thank you. I was beginning to wonder whether there was anyone else in this forum
>willing to discard their preconceived ideas and able to think objectively on
>this subject.

Now, now.  We were having a nice technical discussion, and then you go
and insult everybody who happens to disagree with you.  Yes, it *is*
insulting to say that because I disagree with you, I'm stuck on
preconceived ideas, and I am unable to think objectively.  Grr.
Is this whole thing just a troll, as somebody else suggested elsewhere
in this thread?  Do you want it to devolve into the usual religious
language flame war, complete with ad-hominem arguments?  If so, I don't
particularly want to participate.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
  1996-02-22  0:00               ` Robert Dewar
  1996-02-22  0:00               ` Jon S Anthony
@ 1996-02-24  0:00               ` Valery Croizier
  1996-02-24  0:00               ` Robert A Duff
  1996-02-26  0:00               ` So called Real OO (was blah blah blah...) Jon S Anthony
  4 siblings, 0 replies; 35+ messages in thread
From: Valery Croizier @ 1996-02-24  0:00 UTC (permalink / raw)


In article <Dn9BzB.IMA@world.std.com> bobduff@world.std.com (Robert A Duff) writes:

> You seemed to object strongly to the idea that one can put two types in
> the same package, on the grounds that it decreases encapsulation.  On
> the contrary, it *increases* encapsulation.  When two types are closely
> related to each other, by their nature, *forcing* them to be in separate
> modules means that *more* operations need to be exported from each
> module.
> [...]
> An example is a List type, plus a List_Cursor type.  The List_Cursor
> points at a certain place in the list, and has operations for moving
> forward and/or backward and so forth.  These operations cannot be
> written without visibility on implementation details of *both* types.
> So if class=module, you have to *export* a lot of those implemenation
> details from one of them, so the other one can do what it needs to do.
> Putting them both in the same module, however, actually gives you
> *better* encapsulation, because fewer (and higher-level) operations get
> exported.

Yes, you have to export internals to the other class, but
encapsulation is not weaker, because you can do a selective export, so
that no one (except List_Cursor) can see List's internals.
Putting two types in the same module weakens encapsulation, because it
exports : 
	o *all* internals 
	o to *each other* types 
in that module, while Eiffel allowes the programmer to export only
useful data to classes that need them.
For example, type Person has a field Disease.  Only a Doctor can see
this field, because only doctors are able to identify diseases.
You can't put Person and Doctor in the same package, because :
	o Doctor would see *all* private data of Person
and, that is worse,
	o Person would see all private data of *Doctor*.
Ada's solution works fine with the List_Iterator issue, because
List and List_Cursor aren't complex structures.

> [...]
> So I've heard.  How does this new elegant model deal with the issue I
> mentioned above, about putting list-cursor information inside the list
> itself?  If you have multiple tasks, you definitely want to have two
> tasks iterating through the same shared list (or whatever data
> structure).  Has the standard class library been changed to solve this
> problem?

The issue have little to do with tasking. Even in a sequential
program, a List can have several clients.
As far as Eiffel Libraries are concerned, I don't know them well, but
I've just ckecked ISE's and Tower's Web site, and there is no list in
the Library Kernel.  Of course, vendors provide their own librairies,
and the most prominent ones have traversable lists (at least Sig and
Tower have).

--
Valery CROIZIER




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-22  0:00 ` Valery Croizier
@ 1996-02-24  0:00   ` Robert A Duff
  0 siblings, 0 replies; 35+ messages in thread
From: Robert A Duff @ 1996-02-24  0:00 UTC (permalink / raw)


In article <yrgg2c3dmz1.fsf@borniche.rennes.enst-bretagne.fr>,
Valery Croizier <croizier@rennes.enst-bretagne.fr> wrote:
>If you can simulate Eiffel-like assertions in a trivial way, then
>please show it.

Yes, please do!

>... I know how to check arguments and raise an exception,
>but not so that these checkings are inherited by children, like in Eiffel. 

More importantly, how do you do class invariants in Ada?
The only way I know of, is to put some code in *every*
procedure, which is a pain.

I think that Eiffel's assertions are a pretty nice feature,
especially class invariants, which are hard to do by hand.

- Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-26  0:00                   ` James O'Connor
@ 1996-02-26  0:00                     ` Gene Ouye
  0 siblings, 0 replies; 35+ messages in thread
From: Gene Ouye @ 1996-02-26  0:00 UTC (permalink / raw)



James O'Connor wrote:
> You also realize that to the Smalltalk world, the argument is interesting 
> because, from a Smalltalk perspective, Ada95 and C++ have much more in 
> common than the do differeneces...

True, but most of the arguing in this thread(s) was over Eiffel vs Ada.  
I actually found it refreshing after the endless "C/C++ sucks" threads,
Unfortunately, I've gained most of my Smalltalk knowledge from the 
endless "C++ is not (or, Smalltalk is) a pure OO language" threads on 
comp.object.  Maybe we could use more Smalltalk vs. Ada arguments in 
this group...
                       ;-)

Gene Ouye <geneo@rational.com>






^ permalink raw reply	[flat|nested] 35+ messages in thread

* So called Real OO (was blah blah blah...)
  1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
                                 ` (3 preceding siblings ...)
  1996-02-24  0:00               ` Robert A Duff
@ 1996-02-26  0:00               ` Jon S Anthony
  4 siblings, 0 replies; 35+ messages in thread
From: Jon S Anthony @ 1996-02-26  0:00 UTC (permalink / raw)


In article <Dn9BzB.IMA@world.std.com> bobduff@world.std.com (Robert A Duff) writes:

> You seemed to object strongly to the idea that one can put two types in
> the same package, on the grounds that it decreases encapsulation.  On
> the contrary, it *increases* encapsulation.  When two types are closely
> related to each other, by their nature, *forcing* them to be in separate
> modules means that *more* operations need to be exported from each
> module.

Yes, but in this context (Eiffel) it is mostly irrelevant.  This is
because the two classes can export the "detail stuff" to each other
_only_.  This is from selective export, in particular the optional
part of a feature clause (listing its client classes).  See ETL 7.12
and 7.13.

> mentioned above, about putting list-cursor information inside the list
> itself?  If you have multiple tasks, you definitely want to have two
> tasks iterating through the same shared list (or whatever data
> structure).  Has the standard class library been changed to solve this
> problem?

I think you are confused here.  Iteration is effected by inheriting
from say, list_iteration, when defining some class that needs to be
"iterated over".  In effect, list_iteration supplies only the pattern,
so the particular class has the "cursor" (which is not accessible in
any event).  To handle more than one iteration, you repeatedly inherit
list_iteration (renaming bits as appropriate).  Now, the real problem
here (as has been discussed to death on c.l.e) is that the repeated
inheritance machinery exists in the main to support this iteration
aspect and it is rather complicated and subtle machinery to handle
such a simple thing.  In some respects this bit is the Eiffel
counterpart "dirty laudry" to the "mutual withing" problem in Ada:
Yes, you can get the thing to work, but it isn't pretty.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
1 Williston Road, Suite 4
Belmont, MA 02178

617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-24  0:00               ` Robert A Duff
  1996-02-26  0:00                 ` Matthew B. Kennel
@ 1996-02-26  0:00                 ` Don Harrison
  1 sibling, 0 replies; 35+ messages in thread
From: Don Harrison @ 1996-02-26  0:00 UTC (permalink / raw)


Thanks to numerous respondents for your input on this thread. Hope to reply within
the next couple of days.

No, it is not a troll. Nor is any other I have contributed to.

Don.







^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-23  0:00                 ` Gene Ouye
@ 1996-02-26  0:00                   ` James O'Connor
  1996-02-26  0:00                     ` Gene Ouye
  0 siblings, 1 reply; 35+ messages in thread
From: James O'Connor @ 1996-02-26  0:00 UTC (permalink / raw)


Gene Ouye wrote:
> 
> You realize, of course, that to the outside world (more
> specifically, to many that I know in the C++ community),
> watching this arguing between Eiffel and Ada advocates is
> like watching two hyenas fighting over the last scraps of
> a carcass after the pride of lions has had its fill...
> 
> You also realize, of course, that I'm not trying to say
> that any of this discussion is futile (if I ever find that
> to be true, I will be very depressed!).
> 
> Gene Ouye <geneo@rational.com>

You also realize that to the Smalltalk world, the argument is interesting 
because, from a Smalltalk perspective, Ada95 and C++ have much more in 
common than the do differeneces...

James O'Connor
oconnor@apci.net




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
  1996-02-24  0:00               ` Robert A Duff
@ 1996-02-26  0:00                 ` Matthew B. Kennel
  1996-02-26  0:00                 ` Don Harrison
  1 sibling, 0 replies; 35+ messages in thread
From: Matthew B. Kennel @ 1996-02-26  0:00 UTC (permalink / raw)


Robert A Duff (bobduff@world.std.com) wrote:

: Encapsulation isn't some sort of Goodness, such that the more you have
: of it, the better.  No, you want to encapsulate things at the "right"
: level of granularity for the problem at hand.

I definitely agree with this. 


: An example is a List type, plus a List_Cursor type.  The List_Cursor
: points at a certain place in the list, and has operations for moving
: forward and/or backward and so forth.  These operations cannot be
: written without visibility on implementation details of *both* types.
: So if class=module, you have to *export* a lot of those implemenation
: details from one of them, so the other one can do what it needs to do.
: Putting them both in the same module, however, actually gives you
: *better* encapsulation, because fewer (and higher-level) operations get
: exported.

Of course, Eiffel has selective export, where individual features or sets
of features can be mutually exported and imported.   

Ada gives this set a name.  Better?  Perhaps. 

Eiffel can express notions of "who gets to see what" which are not easily
compatible with strictly hierarchical packages.   (Consider three
classes, A B and C with A sharing some routines with B and some with C, but
B and C sharing nothing. )

: Last time I looked at
Eiffel, the standard library classes put the : cursor movement stuff inside
the list.  That seems like a poor design, : since you can only be looping
through a given list once, at any given : time.  It seems to me that you
badly want the List_Cursor type to be : separate from the List type,
although they *are* part of the same : "module".

I might agree, but there's always the question of efficiency.  Most of the
time you're looping through one list once, needing to allocate extra
objects may be expensive.

What I really want, of course, is Sather's iterators which totally solves
the problem.  :-) 

: >While Eiffel is strong in the OO stakes (it satifies all 3), 

: I agree that Eiffel is superior to Ada with respect to your number 3) --
: that is, the assertion stuff.  Ada does have *some* support for
: assertions.  For example, if I say, "type T is range 1..10;", then
: there's an invariant on T -- all objects of type T have to be in the
: range 1 to 10.  This is pretty weak, compared to Eiffel, though.

: I think it's silly to call that part of OO, though.  It's a completely
: orthogonal issue.  Assertions would be useful in a non-OO language, too.

I wouldn't call it completely orthogonal.  A major point of polymorphic
object oriented programming, and specificially "design by contract" is
validating "who is substitutable for whom here?".  Eiffel expresses this
notion very directly in the combined type AND assertion system, as
descendents must be compatible both in type and assertion set with their
ancestors. 

I'm not a master of Ada, but it seems from reading Ada programs that
this information is not quite as readily obvious. 

: Meyer also said that garbage collection is a fundamental part of OO.
: Nonsense.  GC existed before OO, and it's not necessary in order to
: support the real fundamentals of OO, such as polymorphism.

: Why not just say that GC is a Good Thing, or assertions are a Good
: Thing, or Eiffel's assertions are better than Ada's assertions, or C++
: sucks because it makes it hard to implement GC?  It's silly to use the
: term "OO" as a synonym for "the set of all Good Things".

No argument.  I wait for the day whan "object orientation" is as much
an obvious (and uninteresting) prerequisite as "uses Unicode character set
in parsing". 

: >I think these will all be addressed in time but if none are a concern to you,
: >I suggest taking a look at Eiffel.

: Indeed.  Even if they *are* a concern, it's still instructive to learn
: Eiffel, and to read Meyer's classic book on OOP.  Programming by
: contract is a useful concept in any language.

: - Bob




^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
       [not found] <Do7unJ.1sq@world.std.com>
@ 1996-03-15  0:00 ` Don Harrison
  0 siblings, 0 replies; 35+ messages in thread
From: Don Harrison @ 1996-03-15  0:00 UTC (permalink / raw)


In article <Do7unJ.1sq@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:
:In article <Dns8pv.BDx@assip.csasyd.oz>,
:Don Harrison <donh@syd.csa.com.au> wrote:
:>Various arguments have been advanced to justify co-encapsulation. Below is a
:>collective response.
:>
:>1) Co-encapsulation preserves the symmetry of operands.
:>
:>As indicated in a previous post, the requirements of polymorphism demand that
:>operands are intrinsically asymmetric which suggests that uni-encapsulation is
:>more appropriate.
:
:Correct when there are two tagged types involved (unless you have
:multi-methods, as in CLOS).
:
:However, the symmetry is *not* lost when you have something like:
:
:    procedure Union(X, Y: Set) return Set;
:
:In other OO languages, the parameter X is the special one, and symmetry
:is lost.  Not a big deal, I admit, but I find it slightly cleaner,
:conceptually, to consider X and Y to be on equal footing.

I agree this visually more symmetrical. Of course, the operation still 
semantically belongs to tagged type Set - it is a primitive operation of it.

:
:- Bob
:

Don.








^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: Real OO (was Choice of OO primitives in Ada95)
       [not found] <Do7uyC.4K2@world.std.com>
@ 1996-03-15  0:00 ` Don Harrison
  0 siblings, 0 replies; 35+ messages in thread
From: Don Harrison @ 1996-03-15  0:00 UTC (permalink / raw)


Robert A Duff writes:

:In article <DnKnsz.C8C@assip.csasyd.oz>,
:Don Harrison <donh@syd.csa.com.au> wrote:
:>The only 'cost' is the effort of writing them in the first place but the benefit
:>is enormous because that correctness is propagated through reuse. When assertions
:>are used, there is nothing to fear from inheritance and no reason why all
:>abstractions should not be candidates for reuse by inheritance.
:
:Well, assertions are a nice feature of Eiffel, but they don't
:*guarantee* correctness.  For example, there are some things that can't
:be formalized, like "this procedure prints an error message that is
:easily understood by any competent user".  That's why Eiffel allows some
:assertions to be merely comments, and of course if it's just a comment,
:you can't know for sure that it's obeyed, unless you look at every
:overriding.

Granted. Not everything can be formalised. Of course, it's clearly valuable to 
exploit those aspects of a design that may be formalised.

:>In contrast, assertion-less inheritance propagates errors through reuse.
:>
:>'Frozen' is used when the designer knows the implementation will not change.
:>
:>: Of course, the counter-argument is that you don't always know ahead of
:>: time when you might need dispatching.
:>
:>Exactly.
:>
:>: I'm not sure I agree with Ray Toal, though, that requiring "tagged" is a
:>: Good Thing.  Even without that rule, Ada still gives you control over
:>: whether things dispatch, on a call-by-call basis.  So, I view "tagged"
:>: as simply an efficiency hack.  Efficiency is a Good Thing, too, though.
:>
:>Efficiency hack is a good way of describing it. 
:
:Would you say "frozen" is (merely) an efficiency hack?  I view it as
:partly an efficiency hack, and partly an aid to understanding the
:program.

The two are different in a couple of ways:

a) purpose - 'tagged' concerns dispatching whereas 'frozen' concerns redefinition

b) syntactic necessity
   - 'tagged' is not necessary if the language allows dispatching by default. 
   It is necessary, if dispatching is optional, as in Ada for the purpose of 
   efficiency.
   [I happen to think dispatching by default would be better because the human
   benefits of flexibility and simplicity would outweigh the cost of bigger and 
   better hardware].
 
   - 'frozen' is necessary to indicate whether an operation may be redefined 
   (which is not related to efficiency).

:- Bob

Don.








^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~1996-03-15  0:00 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <DMqHqF.9F1.0.-s@inmet.camb.inmet.com>
     [not found] ` <DMu9yw.5ts@assip.csasyd.oz>
     [not found]   ` <4g2f8v$15lc@watnews1.watson.ibm.com>
1996-02-19  0:00     ` Choice of OO primitives in Ada95 Don Harrison
1996-02-19  0:00       ` Norman H. Cohen
1996-02-19  0:00       ` Robert A Duff
1996-02-20  0:00         ` Don Harrison
1996-02-20  0:00           ` Jon S Anthony
1996-02-22  0:00             ` Real OO (was Choice of OO primitives in Ada95) Don Harrison
1996-02-22  0:00               ` Robert Dewar
1996-02-23  0:00                 ` Gene Ouye
1996-02-26  0:00                   ` James O'Connor
1996-02-26  0:00                     ` Gene Ouye
1996-02-22  0:00               ` Jon S Anthony
1996-02-24  0:00               ` Valery Croizier
1996-02-24  0:00               ` Robert A Duff
1996-02-26  0:00                 ` Matthew B. Kennel
1996-02-26  0:00                 ` Don Harrison
1996-02-26  0:00               ` So called Real OO (was blah blah blah...) Jon S Anthony
1996-02-20  0:00           ` Choice of OO primitives in Ada95 Ray Toal
1996-02-21  0:00             ` Don Harrison
1996-02-23  0:00               ` Robert A Duff
1996-02-22  0:00             ` Bernd Holzmueller
1996-02-23  0:00               ` Robert A Duff
1996-02-23  0:00           ` Robert A Duff
1996-02-21  0:00       ` Robert I. Eachus
1996-02-21  0:00     ` John DiCamillo
1996-02-22  0:00       ` Don Harrison
1996-02-24  0:00         ` Robert A Duff
1996-02-22  0:00 Real OO (was Choice of OO primitives in Ada95) Jean-Pierre Rosen
1996-02-22  0:00 ` Spencer Allain
1996-02-22  0:00 ` Matt Kennel
1996-02-23  0:00   ` Robert A Duff
1996-02-22  0:00 ` Valery Croizier
1996-02-24  0:00   ` Robert A Duff
1996-02-23  0:00 ` Jon S Anthony
     [not found] <Do7uyC.4K2@world.std.com>
1996-03-15  0:00 ` Don Harrison
     [not found] <Do7unJ.1sq@world.std.com>
1996-03-15  0:00 ` Don Harrison

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox