comp.lang.ada
 help / color / mirror / Atom feed
* More questions...
@ 1999-03-07  0:00 Michael Young
  1999-03-08  0:00 ` Steve Doiel
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Michael Young @ 1999-03-07  0:00 UTC (permalink / raw)


I have two questions about Ada; more will certainly follow.

1) I've heard it said here that Ada, compared to other languages, is
"reader-friendly" at the expense of being "writer-unfriendly". I
understand the need to be reader friendly. I'm curious why you feel it
is friendlier to read than, say, C++.

2) Robert Dewar stated some time ago that finalize should be used
sparingly because of performance concerns. Is this still true of GNAT
3.11? More broadly, is this a language issue, or a feature specific only
to certain GNAT or other implementation? Destructors in C++ are simply
normal function calls. Are controlled types significantly different from
other types to make this unrealistic?

Thanks.

Michael.






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

* Re: More questions...
  1999-03-07  0:00 More questions Michael Young
  1999-03-08  0:00 ` Steve Doiel
@ 1999-03-08  0:00 ` James S. Rogers
  1999-03-08  0:00   ` Hyman Rosen
  1999-03-09  0:00 ` Samuel Mize
  1999-03-09  0:00 ` Samuel Mize
  3 siblings, 1 reply; 9+ messages in thread
From: James S. Rogers @ 1999-03-08  0:00 UTC (permalink / raw)



Michael Young wrote in message <7bvb4j$lt0$1@remarQ.com>...
>I have two questions about Ada; more will certainly follow.
>
>1) I've heard it said here that Ada, compared to other languages, is
>"reader-friendly" at the expense of being "writer-unfriendly". I
>understand the need to be reader friendly. I'm curious why you feel it
>is friendlier to read than, say, C++.

C and, because of C compatibility, C++ syntax is written to minimize the
number of keystrokes required to create a program.  In the early 1970's
this was viewed as a way of increasing programmer productivity.
Unfortunately,
C++ has taken the very terse syntax of C and added new functionality
while trying not to increase the number of additional keywords and
operators.
The result is a heavy overloading of already heavily overloaded operators.
Think of all the uses of the '*' and '&' operators in C++.  Correct
understanding
of these operators is highly context dependent.

Some examples taken from page 79 of "Object Oriented Programming
Using C++" by Ira Pohl:

int      i = 5;     // i is located in memory with rvalue 5
int*    p = &i;   // p is located in memory with rvalue &i
int&   r = i;      // r and i are the same object
int&* s = p;   // s and p are the same object

Now, the example above seems a little confusing.  It claims that r and i are
the
same object. At the same time it is true that references such as r are
implemented using pointers.  C++ simply provides a cleaner and safer
way to use a pointer when it is declared as a reference.  The statement
above would lead you to believe that r is merely an alias for i.

The nearest Ada equivalents to the C++ examples above are:

i : aliased integer := 5;    -- i is located in memory and is initialized
with the 5
type Int_Access is access all integer; -- define a general access type
p : Int_Access := i'access; -- p is located in memory with value of i'access

Ada does not have a direct equivalent to references.  In fact, Ada access
types
are as safe as C++ references while also being useful in all Ada data
structures.
C++ references are always constants.  A reference cannot change the object
it references. The reference object may or may not be constant.

C++ reference types cannot be elements of an array because references must
be initialized, while arrays cannot be initialized in C++.

As far as how readable the two languages are, try the following test.

Find a person who does not know Ada or C++.
Show that person the following code fragments.

#include <streams.h>
main ()
{
   for(int Count = 1; Count < 11; Count++)
      cout << Count << endl;
}

with Ada.Text_Io;
procedure Count_To_Ten is
begin
   for Count in 1..10 loop
      Ada.Text_Io.Put_Line(Integer'Image(Count));
   end loop;
end Count_To_Ten;

Ask this person what each code fragment does.

>2) Robert Dewar stated some time ago that finalize should be used
>sparingly because of performance concerns. Is this still true of GNAT
>3.11? More broadly, is this a language issue, or a feature specific only
>to certain GNAT or other implementation? Destructors in C++ are simply
>normal function calls. Are controlled types significantly different from
>other types to make this unrealistic?

This is not a compiler specific issue.  It is a language level issue.


Controlled types have the overhead of calling finalize each time an object
of the controlled type goes out of scope. Other types in Ada do not call a
finalize procedure when they go out of scope. Finalization is also called
during assignment operations for all temporary objects created and destroyed
during the actual assignment operation. Ada uses temporary objects so
that the case where A := A is properly handled.

C++ needs constructors for all classes because C++ requires dynamic
allocation and deallocation of objects to achieve polymorphism.  Ada allows
the programmer to decide whether or not to use dynamic allocation and
deallocation. Ada can achieve polymorphism with or without dynamic
allocation. This means that Ada does not always need a destructor.
Robert Dewar was warning against the use of Controlled types because they
impose an overhead which may not be necessary.  If your design uses no
dynamic allocation you may not need the facilities of Controlled types.

Jim Rogers
Colorado Springs, Colorado






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

* Re: More questions...
  1999-03-07  0:00 More questions Michael Young
@ 1999-03-08  0:00 ` Steve Doiel
  1999-03-08  0:00 ` James S. Rogers
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 9+ messages in thread
From: Steve Doiel @ 1999-03-08  0:00 UTC (permalink / raw)



Michael Young wrote in message <7bvb4j$lt0$1@remarQ.com>...
>I have two questions about Ada; more will certainly follow.
>
>1) I've heard it said here that Ada, compared to other languages, is
>"reader-friendly" at the expense of being "writer-unfriendly". I
>understand the need to be reader friendly. I'm curious why you feel it
>is friendlier to read than, say, C++.
>

For an illustration, point your web browser to:
  http://www.lucent.com/ideas2/perspectives/bltj/
Select "Current"
Then select "A Software Fault Prevention Approach in Coding and Root Cause
Analysis".

This document is not a contrast of Ada and C, it is an analysis of defects
found in a sizable switching system that was implemented in C.  The document
gives a number specific examples of common coding errors found in the
system.

In my opinion none of these coding errors would be present if the code were
written in Ada.  These errors were the result of the tricky syntax in C.

It may be easier to read "good" C code than "bad" Ada code.  But with my
luck (and experience) I am more likely to have to read "bad" C code and
"average" Ada code.


>2) Robert Dewar stated some time ago that finalize should be used
>sparingly because of performance concerns. Is this still true of GNAT
>3.11? More broadly, is this a language issue, or a feature specific only
>to certain GNAT or other implementation? Destructors in C++ are simply
>normal function calls. Are controlled types significantly different from
>other types to make this unrealistic?
>


The use of finalization may add function calls to code that appears to
consist of simple assignments.  The same is true of C++.  While I don't know
how Ada and C++ compare when it comes to performance of Finalization versus
destructors, both cases add a lot of hidden action to othewise simple
looking code.

SteveD






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

* Re: More questions...
  1999-03-08  0:00 ` James S. Rogers
@ 1999-03-08  0:00   ` Hyman Rosen
  1999-03-10  0:00     ` Matthew Heaney
  0 siblings, 1 reply; 9+ messages in thread
From: Hyman Rosen @ 1999-03-08  0:00 UTC (permalink / raw)


"James S. Rogers" <jimmaureenrogers@worldnet.att.net> writes:
> int&   r = i;      // r and i are the same object

> Now, the example above seems a little confusing.
> It claims that r and i are the same object.

It is not confusing at all. In fact, r and i *are* the same object.

> At the same time it is true that references such as r are
> implemented using pointers.

The fact that *in some cases* a pointer to the referenced object may
be created by the implementation is completely irrelevant to the C++
concept that a reference is an alias of the referenced object.

> C++ simply provides a cleaner and safer way to use a pointer when it
> is declared as a reference.  The statement above would lead you to
> believe that r is merely an alias for i.

In C++, references are not pointers. They are aliases for objects.
A reference always refers to the same object from the moment it is
created. It is true that careless programming can leave a reference
dangling by destroying its aliased object out from under it, since,
as has been mentioned here before, C++ defaults to "unsafe".

> Ada does not have a direct equivalent to references.  In fact, Ada
> access types are as safe as C++ references while also being useful
> in all Ada data structures.

C++ reference types have little to do with safety, and much to do with
operator overloading. Their main purpose is to permit the return value
of a function to be the alias of an existing object, so that further
operations may be performed on it, and to avoid copying of possibly
large objects as function parameters.

	template <typename T, int N> class fixed_array
	{
		T theArray[N];
	public:
		T &operator[] (int n) { return theArray[n]; }
	};
	fixed_array<double, 6> b;
	b[3] = 7.9;

> C++ references are always constants.  A reference cannot change the object
> it references. The reference object may or may not be constant.
> C++ reference types cannot be elements of an array because references must
> be initialized, while arrays cannot be initialized in C++.

A much better analogy is to compare C++ references with Ada procedure
parameters. The compiler must (I believe) implement pass-by-reference
for at least certain kinds of parameters. In Ada, you certainly would
not expect to be able to reseat a procedure parameter to refer to some
object other than the one passed, nor would you expect to be able to
have an array of in out parameters!


> As far as how readable the two languages are, try the following
> test.  Find a person who does not know Ada or C++.  Show that person
> the following code fragments.

This is a straw man. Certainly no programming language is designed to
be understood by people who do not know it!

>       cout << Count << endl;
>       Ada.Text_Io.Put_Line(Integer'Image(Count));
> 
> Ask this person what each code fragment does.

I suspect that the person would wonder where the forgotten close quote
goes in the Ada code. If he wanted to print two numbers on the same line,
he might wonder what to call, assuming he even realized that put_line
appended the terminator. Once he knew C++, he might wonder why he had to
name the type of Count when trying to print it.

> C++ needs constructors for all classes because C++ requires dynamic
> allocation and deallocation of objects to achieve polymorphism.  Ada
> allows the programmer to decide whether or not to use dynamic
> allocation and deallocation. Ada can achieve polymorphism with or
> without dynamic allocation. This means that Ada does not always need
> a destructor.

Once again, this is vastly confused. First, C++ does *not* need
constructors for all classes. Constructors and destructors are
used to appropriately initialize and clean up objects. When no
such work is needed the construct does not need to appear. And
one can have either a constructor or destructor without the other.
Second, it is false as well that dynamic allocation is required
for polymorphism. Objects may be created dynamically on the heap,
automatically on the stack, or statically in fixed memory, and
they will all act polymorphically if they are part of a polymorphic
hierarchy.

> Robert Dewar was warning against the use of Controlled types because they
> impose an overhead which may not be necessary.  If your design uses no
> dynamic allocation you may not need the facilities of Controlled types.

I don't remember that thread, but I assume that he is correct.
I also assume that he may at this moment be writing to correct
your mistakes just as I am!




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

* Re: More questions...
  1999-03-07  0:00 More questions Michael Young
                   ` (2 preceding siblings ...)
  1999-03-09  0:00 ` Samuel Mize
@ 1999-03-09  0:00 ` Samuel Mize
  1999-03-09  0:00   ` Hyman Rosen
  1999-03-10  0:00   ` robert_dewar
  3 siblings, 2 replies; 9+ messages in thread
From: Samuel Mize @ 1999-03-09  0:00 UTC (permalink / raw)


Michael Young <nobody@all.org> wrote:
> 2) Robert Dewar stated some time ago that finalize should be used
> sparingly because of performance concerns. ...
> Destructors in C++ are simply
> normal function calls. Are controlled types significantly different from
> other types to make this unrealistic?

Was he saying that Finalize should be used sparingly compared to
C++ destructors?

I would assume that he was saying it should not be used unless needed,
because it adds a function call at every assignment statement, and
when the variable goes out of scope.

Ada is often used in time-critical embedded systems, where needless
procedure-call overhead may be a significant cost.

OTOH, when you assign a new value to an object with a destructor, does
C++ call the destructor before assigning the new value?  Or is that even
a meaningful question for C++?

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: More questions...
  1999-03-07  0:00 More questions Michael Young
  1999-03-08  0:00 ` Steve Doiel
  1999-03-08  0:00 ` James S. Rogers
@ 1999-03-09  0:00 ` Samuel Mize
  1999-03-09  0:00 ` Samuel Mize
  3 siblings, 0 replies; 9+ messages in thread
From: Samuel Mize @ 1999-03-09  0:00 UTC (permalink / raw)


Michael Young <nobody@all.org> wrote:
> 1) I've heard it said here that Ada, compared to other languages, is
> "reader-friendly" at the expense of being "writer-unfriendly". I
> understand the need to be reader friendly. I'm curious why you feel it
> is friendlier to read than, say, C++.

This is more a touchstone for comparing possible language constructs to
put into Ada, than a touchstone for comparing Ada to other languages.

And I'm not sure that "friendly" is the most accurate term for it.  That's
a subjective judgement, and some people find

  while (*a++=*b++);

to be "friendlier" than the Ada equivalent.

I'd say that the idea is that the reader's first impression of the code
should be both unambiguous and correct.

One element is explicitness over conciseness.  For instance, in Ada,
you can freely convert between separate integer types, just as you can
in C (and I assume in C++).  However, you have to explicitly state that
you are doing so.  Aside from detecting typos (and thinkos), this tells
the later code reader that you really did intend to do that.

Best,
Sam Mize

-- 
Samuel Mize -- smize@imagin.net (home email) -- Team Ada
Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam




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

* Re: More questions...
  1999-03-09  0:00 ` Samuel Mize
@ 1999-03-09  0:00   ` Hyman Rosen
  1999-03-10  0:00   ` robert_dewar
  1 sibling, 0 replies; 9+ messages in thread
From: Hyman Rosen @ 1999-03-09  0:00 UTC (permalink / raw)


Samuel Mize wrote:
> OTOH, when you assign a new value to an object with a destructor, does
> C++ call the destructor before assigning the new value?  Or is that even
> a meaningful question for C++?

In C++ classes may have user-defined assignment operators. If a class has
such a thing, then it is invoked when the assignment is done, and it is
responsible for doing the necessary cleanup work. If a class does not have
a user-defined assignment operator, then the default behavior is to treat
assignment as a field-by-field copy, recursively invoking other user-defined
assignment operators if fields are themselves class objects.

Note that in C++, assigning to an object does not have the semantics of
destroying the object and replacing it with a new one. The object is
considered to be the same before and after the assignment. It merely has
had its value changed in some fashion.




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

* Re: More questions...
  1999-03-09  0:00 ` Samuel Mize
  1999-03-09  0:00   ` Hyman Rosen
@ 1999-03-10  0:00   ` robert_dewar
  1 sibling, 0 replies; 9+ messages in thread
From: robert_dewar @ 1999-03-10  0:00 UTC (permalink / raw)


In article <7c40uu$14lu@news3.newsguy.com>,
  Samuel Mize <smize@imagin.net> wrote:
> Was he saying that Finalize should be used sparingly
> compared to C++ destructors?

No, he was not :-)
>
> I would assume that he was saying it should not be used
> unless needed, because it adds a function call at every
> assignment statement, and when the variable goes out of
> scope.

That's what he was saying!

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




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

* Re: More questions...
  1999-03-08  0:00   ` Hyman Rosen
@ 1999-03-10  0:00     ` Matthew Heaney
  0 siblings, 0 replies; 9+ messages in thread
From: Matthew Heaney @ 1999-03-10  0:00 UTC (permalink / raw)


Hyman Rosen <hymie@prolifics.com> writes:

> "James S. Rogers" <jimmaureenrogers@worldnet.att.net> writes:
> > Ada does not have a direct equivalent to references.  In fact, Ada
> > access types are as safe as C++ references while also being useful
> > in all Ada data structures.
> 
> C++ reference types have little to do with safety, and much to do with
> operator overloading. Their main purpose is to permit the return value
> of a function to be the alias of an existing object, so that further
> operations may be performed on it, and to avoid copying of possibly
> large objects as function parameters.


The mechanism for this sort of thing in Ada is to have a function that
returns a pointer designating the object, and then dereference the result
of the function. 

For example, suppose you have a stack of integers.  The bullet-proof way
to set the top item via a "reference" (really, a pointer) is to declare
the operation

  function Set_Top (Stack : access Stack_Type) return Item_Access;

and then do this:

  Set_Top (Stack'Access).all := 10;

Using this approach, you can never have a dangling reference.

It's not as nice as the C++ way:

  Set_Top (Stack) := 10;

but it's reasonably close.  

In Ada95 you pay a small amount of syntactic overhead, but the benefit
is that you can't get a dangling reference.

If you know what you're doing, you can shorten the statement to

  Set_Top (Stack).all := 10;


I discuss this technique in my article "Collections of Limited Items" in
the ACM patterns archive.

<http://www.acm.org/archives/patterns.html>














  




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

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

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-03-07  0:00 More questions Michael Young
1999-03-08  0:00 ` Steve Doiel
1999-03-08  0:00 ` James S. Rogers
1999-03-08  0:00   ` Hyman Rosen
1999-03-10  0:00     ` Matthew Heaney
1999-03-09  0:00 ` Samuel Mize
1999-03-09  0:00 ` Samuel Mize
1999-03-09  0:00   ` Hyman Rosen
1999-03-10  0:00   ` robert_dewar

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