[net.lang] Abstraction In Ada

mauney@ncsu.UUCP (Jon Mauney) (06/18/84)

Ada is a complicated and rather ponderous language,  and I can 
understand why people might not like it.  But I think that one
of Ada's strengths is a pretty good data abstraction facility.
Therefore I would like to see an elaboration of any complaints
in that area.

Specifically:  (from mit!nessus)

> To do a good job with data abstraction, you really need heap-based
> allocation with automatic garbage collection.  Ada doesn't support this.

I don't see how this follows,  except that lack of a garbage-collected
heap restricts your ability to implement an ADT using a garbage-collected
heap.  There are advantages and disadvantages to heap allocation of
data objects;  I don't see how they relate to abstraction.

> Also, Ada's private type system is completely messed up.  "Private
> types" have their assignment and equality operations provided by the
> system.  This is the wrong thing since two abstract objects may be
> different from the concrete view (the view that Ada's "=" operation
> takes), but equal from the abstract point of view.  And the assignment
> operation is supposed to copy the object being assigned, but the system
> provided operation can't do that right either.  You can do a little
> better with "limiited private types".  You can then provide your own "="
> operation, but you still can't provide your own ":=" operation.  And
> even if you do define your own "=" operation for a limited private type,
> Ada then won't allow you to use "=" on a composite type that contains
> that type.

Ada gives the "package" designer three choices: (A) a type can be
declared right in the package specification, which means everyone can
use the information to write code that is totally dependent on the
particular representation chosen. (B) a type can be declared "private,"
which means that even though everyone knows how the type is
implemented, they can't write code that depends on it.  Two operations,
assignment and equality testing, are provided by the system.  This is
convenient in many cases, because the system-supplied operations are
exactly what you want. (C) a type can be declared "limited private."
In this case the only operations supplied by the system are declaration of
variables (an essential ability) and passing as parameter (also
essential).  This is useful in many cases, because the system-supplied
operations are not appropriate to the particular abstraction or
implementation.  The '=' operator may be overloaded, and definition of
'=' automatically implies definition of '/='.  Sad to say, ':=' is
not an operation that can be overloaded, and assignment of limited
private types must be done using a different syntax.  This system is
not without its defects, but is it really so horrible?

> Basically, Ada is just gross.  Bleah!

The above opinion is frequently heard. Practically every language has been
substituted for Ada at some point.  This prompts me to issue the following
challenge,  pretty much unrelated to the above discussion:
     Can you name a language that will not elicit a "Bleah" from someone
on the net?  Languages so obscure that no one on the net has heard of them
do not qualify.  Mail any suggestions to me; I will collect them and try
to find an objective method of getting a response from the net at large.
The winner will receive a barbeque sandwich from the Blue Mist, Asheboro, NC.

-- 

_Doctor_                           Jon Mauney,    mcnc!ncsu!mauney
\__Mu__/                           North Carolina State University

nessus@mit-eddie.UUCP (Doug Alan) (06/22/84)

>	From: mauney@ncsu.UUCP (Jon Mauney)

>>		To do a good job with data abstraction, you really need
>>		heap-based allocation with automatic garbage collection.
>>		Ada doesn't support this.

>	I don't see how this follows, except that lack of a
>	garbage-collected heap restricts your ability to implement an
>	ADT using a garbage-collected heap.  There are advantages and
>	disadvantages to heap allocation of data objects; I don't see
>	how they relate to abstraction.

If data abstraction is done right, data types that are added to the
languange should look just like data types that are already built into
the language.  Stack-based allocation doesn't work right because you
have to know how much space you will use before you use it.  This is not
very abstract.  You might not know how much space you need.  Heap-based
allocation where explicit deallocation is required doesn't work right
because you can have dangling references.  On object isn't very abstract
if you try to reference it and find out it's been turned to garbage.
Explicit dealocation also violates modularity because one part of a
program has to take responsibilty for deallocating an object and it has
to know when everyone else is no longer using it.  This compromises
modularity.

I will demonstrate by example.  Let's say that you want to implement a
bignum (integer with arbitrary size) abstraction.  In order to be
abstract, the bignum data type should be just as first class as any
other number type.  If you use stack-based allocation, you will have to
worry about reserving the right amount of space in advance.  But gee,
you don't have to do this with number types that are built in.  If you
use heap-based allocation with explicit dealocation, you will have to
worry about dealocating a bignum when you are finished with it.  But
gee, you don't have to do this with number types that are built in.

>	(C) a type can be declared "limited private."  In this case the
>	only operations supplied by the system are declaration of
>	variables (an essential ability) and passing as parameter (also
>	essential).  This is useful in many cases, because the
>	system-supplied operations are not appropriate to the particular
>	abstraction or implementation.  The '=' operator may be
>	overloaded, and definition of '=' automatically implies
>	definition of '/='.  Sad to say, ':=' is not an operation that
>	can be overloaded, and assignment of limited private types must
>	be done using a different syntax.  This system is not without
>	its defects, but is it really so horrible?

Yes, it's gross!  You also forgot to mention that if a composite type
has components of a limited private type "=" is not available for
objects of the composite type.

>	Can you name a language that will not elicit a "Bleah" from
>	someone on the net?  Languages so obscure that no one on the net
>	has heard of them

CLU is my choice.  It is small, simple, clean, powerful, and general.
It is also quite efficient.  It sometimes sacrifices power for the sake
of simplicity.  It doesn't do type inheritance, or run-time type
generics, so it's not suitable for everything.  But for what it tries to
do, it does remarkably well -- it has the best trade off of
power/easy-of-use/efficiency I've ever seen.

Death to Ada!  Long live CLU.
-- 
				-Doug Alan
				 mit-eddie!nessus
				 Nessus@MIT-MC

				"What does 'I' mean"?

 

brad@umcp-cs.UUCP (06/25/84)

<peer pressure made me type this>

Let me respond to a few points in the Ada abstraction debate.

>>>		From: nessus@mit-eddie.UUCP
>>>		To do a good job with data abstraction, you really need
>>>		heap-based allocation with automatic garbage collection.
>>>		Ada doesn't support this.

Not true.  The Ada Language Reference Manual (LRM) says the following:
(section 4.8, page 4-25)

	"An implementation must guarantee that any object created by the
	evaluation of an allocator remains allocated for as long as this
	object or one of it's subcomponents is accessable directly or
	indirectly, that is as long as it can be denoted by some name.
	Moreover, if an object or one of its subcomponents belongs to a task
	type, it is considered to be accessible as long as the task is not
	terminated.  An implementation may (but need not) reclaim the
	storage occupied by an object created by an allocator, once this
	object has become inaccessible."

This last sentence gives an implementor the choice of providing garbage
collection.  You see, it's an implementation issue.  You should note that in
some cases (such as real-time systems) it may be a bad thing to have garbage
collection since your system may be effectivly halted for noticable periods
of time.

>From: nessus@mit-eddie.UUCP
>If data abstraction is done right, data types that are added to the
>languange should look just like data types that are already built into
>the language.  Stack-based allocation doesn't work right because you
>have to know how much space you will use before you use it.  This is not
>very abstract.  You might not know how much space you need.  Heap-based
>allocation where explicit deallocation is required doesn't work right
>because you can have dangling references.  On object isn't very abstract
>if you try to reference it and find out it's been turned to garbage.
>Explicit dealocation also violates modularity because one part of a
>program has to take responsibilty for deallocating an object and it has
>to know when everyone else is no longer using it.  This compromises
>modularity.

Ada has been designed so that dangling references are eliminated.  An object
isn't deallocated (and possibly garbage collected) until all references are
elimated.  If you are used to a language like C, where many objects are
unneccessarily global in scope, then you might feel this is a problem, but
in Ada, objects can be declared with an appropriate scope.

>I will demonstrate by example.  Let's say that you want to implement a
>bignum (integer with arbitrary size) abstraction.  In order to be
>abstract, the bignum data type should be just as first class as any
>other number type.  If you use stack-based allocation, you will have to
>worry about reserving the right amount of space in advance.  But gee,
>you don't have to do this with number types that are built in.  If you
>use heap-based allocation with explicit dealocation, you will have to
>worry about dealocating a bignum when you are finished with it.  But
>gee, you don't have to do this with number types that are built in.

Again, in Ada, one can implement the "bignum" using dynamic allocation (i.e.
access types) and you do not have to do explicit deallocation.  Of course
there is the problem of possibly running out of memory, but that is only if
your implementation does not do garbage collection (again, an implementation
issue).  I wonder how much memory your "bignum" scheme would use anyway.  I
won't even mention virtual memory.

>>	From:  mauney@ncsu.UUCP (Jon Mauney)
>>	(C) a type can be declared "limited private."  In this case the
>>	only operations supplied by the system are declaration of
>>	variables (an essential ability) and passing as parameter (also
>>	essential).  This is useful in many cases, because the
>>	system-supplied operations are not appropriate to the particular
>>	abstraction or implementation.  The '=' operator may be
>>	overloaded, and definition of '=' automatically implies
>>	definition of '/='.  Sad to say, ':=' is not an operation that
>>	can be overloaded, and assignment of limited private types must
>>	be done using a different syntax.  This system is not without
>>	its defects, but is it really so horrible?

>Yes, it's gross!  You also forgot to mention that if a composite type
>has components of a limited private type "=" is not available for
>objects of the composite type.

I don't understand why it's so gross.  The lack of overloading for ":=" has
it's trade-offs.  One of the reasons that limited private types may not be
assigned is so that copying of secure or limited resources may be forbidden.

I don't understand under what circumstances that operation "=" for type A
shoud be inherited for objects of type B that contain objects of type A.  If
type B is a record, for example, then the subcomponent of an object of type
B (i.e. one of type A) still has the "=" operation.  Could you give me an
example?

Also, for a discussion of Object Oriented Design and Ada, pick up a copy of
Grady Booch's book, "Software Engineering with Ada".  It is the definite
reference for Object Oriented Design and how it can be used in Ada.

			Brad Balfour
		arpa	brad@maryland
		csnet	brad@umcp-cs
		uucp	{seismo,allegra}!umcp-cs!brad

mauney@ncsu.UUCP (Jon Mauney) (06/25/84)

Q: Is it possible to have a good data abstraction mechanism AND stack
allocation of objects?

A: It depends on whom you believe:

>>>		To do a good job with data abstraction, you really need
>>>		heap-based allocation with automatic garbage collection.
>>>		Ada doesn't support this.

>>	I don't see how this follows, except that lack of a
>>	garbage-collected heap restricts your ability to implement an
>>	ADT using a garbage-collected heap.  There are advantages and
>>	disadvantages to heap allocation of data objects; I don't see
>>	how they relate to abstraction.

> If data abstraction is done right, data types that are added to the
> languange should look just like data types that are already built into
> the language.  Stack-based allocation doesn't work right because you
> have to know how much space you will use before you use it.  This is not
> very abstract.  You might not know how much space you need.

The truth of the above statement depends on the binding of the word "you".
It is unavoidable that someone must know how much space to allocate for
a data object;  the question is how widespread must that knowledge be?
In CLU, only the defining cluster need know the concrete size of an object,
since variables are always pointers to objects.  This promotes good 
independence of modules, but:  since variables are not automatically 
bound to data objects, each data type must provide a create function
that must be explicitly called to allocate space (yuck, ugly!).  Ordinary
assignment statements merely copy pointers; to get an identical copy of
an object you must call a function (yuck, ugly!).  Since variables are
pointers, there are lots of aliases;  unexpected side effects can only 
be prevented by restrictions on the language  or coding style.

In Ada, variables are automatically allocated on the stack, just like
in Pascal and C (ah! comfortable familiarity.  keep that nasty future away
as long as possible).  This means that the users of an abstract type
must know how big it is.  But who is it that has to know?  Certainly not
the programmer -- programmer's don't ordinarily take an active role in
allocating space.  The compiler has to know.  Therefore,  the interface
for an abstraction must be available before any code using the abstraction
can be compiled.  The same is true of any language, else how could the
compiler know what operations are defined for the type.  The difference
is that the concrete representation must be included in the interface,
and all code using an abstraction must be recompiled whenever the 
representation is changed.  The restrictions on order of compilation
can be made transparent to the programmer by providing an automatic 'make'
facility.
In short,  complications in the compiler are traded against stack allocation
of data.  The benefits of the trade-off may be debated,  but I do not see
a great impact on the actual program code.

> I will demonstrate by example.  Let's say that you want to implement a
> bignum (integer with arbitrary size) abstraction.  In order to be
> abstract, the bignum data type should be just as first class as any
> other number type.  If you use stack-based allocation, you will have to
> worry about reserving the right amount of space in advance.  But gee,
> you don't have to do this with number types that are built in.  If you
> use heap-based allocation with explicit dealocation, you will have to
> worry about dealocating a bignum when you are finished with it.  But
> gee, you don't have to do this with number types that are built in.

Like I said,  not having a garbage-collected heap makes it hard to
implement those types for which you want a garbage-collected heap.
This is independent of the abstraction issue.

I find CLU to be a simple and powerful language.  I find Ada to
be a complicated and powerful language.  In general, I prefer less
complicated languages.  But your specific complaints make no sense to me.
-- 

_Doctor_                           Jon Mauney,    mcnc!ncsu!mauney
\__Mu__/                           North Carolina State University

(I give up. What does 'I' mean?)