comp.lang.ada
 help / color / mirror / Atom feed
From: "Nick Roberts" <nickroberts@callnetuk.com>
Subject: Re: Ragged Array Proposal
Date: 1999/09/23
Date: 1999-09-23T00:00:00+00:00	[thread overview]
Message-ID: <37eaa24b@eeyore.callnetuk.com> (raw)
In-Reply-To: 37EA4E91.1D4D1FC@averstar.com

Tucker Taft <stt@averstar.com> wrote in message
news:37EA4E91.1D4D1FC@averstar.com...
[...]
| If you change Command_String_Ptr to be "access constant String;" then
| the recommended implementation does *not* duplicate the static data.
| It is link-time allocated and initialized.  This might vary by compiler,
| but anything having to do with link-time initialization is an
"optimization,"
| so that is true even for static constants.  I know at least that the
| Aonix and Green Hills Ada 95 compilers statically allocate and initialize
| allocators for access-to-constant types.  I haven't checked GNAT.
[...]

My contention is that using an access type and allocators is unappealing
simply because the programmer is forced to use an access type and allocators
for doing something _really simple_: declaring an array of strings!

With the greatest respect, it is perhaps easy for those of you who are
steeped in knowledge of the language to overlook this (and there can be no
arguing that STT is steeped in knowledge of the language!).

Try telling a C++ programmer that, in Ada, they have to declare an access
type, and then repeat the "new String'("xyz")" incantation for every string,
just to declare an array of strings, and they might be likely to say "Ada?
No thanks, I'll stick to C++, if you don't mind."

Frankly, the pre-allocation trick (which is fine and dandy in all other
respects) only makes things worse from this point of view (simplicity for
the programmer), since it makes it looks like something is happening
(dynamic allocation) which is actually not. I agree with the idea that Ada
language constructs should not be too divorced from their likely underlying
implementations, and this seems like a rare example of Ada committing this
sin. I would agree that ragged arrays commit the same sin, but I would say
less so.

To those who argue that adding ragged arrays would add unnecessary
complexity to the language, my reply is not to confuse complexity of the
language with complexity of _using_ the language. It would unarguably
simplify the language tremendously to remove arrays, records, generics,
tagged types, subprograms, etc., but it wouldn't simplify using the
language. My argument is that ragged arrays would add relatively little to
the complexity of the language, but would, in practice, very often simplify
using the language a great deal.

I think the example of the ragged array in a record demonstrates the most
serious reason for introducing ragged arrays. Think about the likely
underlying implementation for this (an array of pointers or offsets and a
block of data, all totally internal to the record), and then think about how
the same thing could be done in existing Ada 95.

In general, the closest you can get in Ada 95 is to use an access type
(either to the array as a whole, or to the components of the array), and
dynamic allocation. The ragged array will generally be more efficient: if
your program is going to have multiple objects constrained to the same
subtype of the record (a very likely scenario), the 'dope' information only
needs to be stored once, saving memory; the necessity to call upon the
allocator to allocate either the array or its components is avoided, saving
processor time; the necessity to declare access types and mess around with
the associated paraphernalia can be avoided (saving hair, in extreme cases
:-).

Ted Dennison wrote:

| One thing confuses me about your proposal. You say that when the array
| is declared all the elements will be constrained. But then you say that
| you can dynamicly change elements. Are you saying that if I try to
| assign a 5 character string into an array element that is a 4 character
| string, the compiler would accept it? If so, how about if a function
| returns a 5 character string? Or how about if the 4 character string
| element in the ragged array is passed into a subprogram as an "out" or
| "in out" parameter?

I'm not quite sure where I say this, Ted, but I hope I can clarify things
using your examples.

The subtypes of the components of a ragged array, called the 'profile' of
the array, form part of the constraint of the array. Supposing we declared
an 'array of strings' ragged array type:

type String_Array is array (Positive range <>) of String;

we could then declare an object of this type, constrained to, say, three
components, with a profile of, say, a 3-character string, a 4-character
string, and a 5-character string:

People: String_Array(1..3)(String(1..3),String(1..4),String(1..5));

Note the 'profiled constraint': an ordinary index constraint, followed by an
'array profile'. Alternatively, the object could have been constrained by an
initial value:

People: String_Array := ("Tom","Dick","Harry");

(Note the nice, simple syntax.) Either way, People is now permanently
constrained, both in terms of its indexes and its profile. The assignment:

People(2) := "Jane";

would be perfectly all right, since People(2) is a 4-character string.
However, either of:

People(3) := "Jane";
People(2) := "Emily";

would raise Constraint_Error. Nothing can change either the index subtype or
the profile of People, and its components follow the same rules they would
as stand-alone objects.

Since the actual parameter matching an 'out' or 'in out' mode formal
parameter must be an object, and all objects of an array type - including my
proposed ragged array type - must be constrained, the constraint, including
the profile of a ragged array, would be passed in upon a call to the
procedure, just as with all other mutable types, and the procedure could not
change the constraint.

As for a function result, since function return types (as well as any
subprogram parameter types) are allowed to be unconstrained, a function
could be declared which had simply String_Array as its return type, and then
the function could return results with any compatible subtype (i.e. any
index range and any profile).

For example, a function could be defined to reverse the order of the
components of a string array:

function Reverse_Order (A: in String_Array) return String_Array;

and then the expression Reverse_Order(("Tom","Dick","Harry")) would return
the array ("Harry","Dick","Tom").

It is significant to note that the implementation of this function would
have to be highly inefficient (involving repeated slicing and
concatenating). This illustrates that there would often be situations where
an array of access values would be far preferable to a ragged array. My
argument is that, conversely, there would often be situations where a ragged
array would be preferable to an array of access values.

I'm grateful to Ted for his compliment on the appearance of my site (I'll
try to maintain the standard!), and I'm very grateful to people taking the
time to look at my proposal and post comments.

Best wishes,

-------------------------------------
Nick Roberts
http://www.callnetuk.com/home/nickroberts
http://www.adapower.com/lab/adaos
-------------------------------------

PS: I'm not at all emotionally attached to the nomenclature that I've
invented (even the name "ragged array"), and not entirely happy with it, so
suggestions for improvements gratefully accepted. The same goes for the
syntax.

PPS: Hold on to your hats, folks! Next up is going to be a 'single derived
object' proposal. I haven't finished with you yet :-)








  reply	other threads:[~1999-09-23  0:00 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <37e7c08e@eeyore.callnetuk.com>
1999-09-22  0:00 ` Ragged Array Proposal Ted Dennison
1999-09-22  0:00   ` Ray Blaak
1999-09-23  0:00     ` Ted Dennison
1999-09-23  0:00     ` Tucker Taft
1999-09-23  0:00       ` Nick Roberts [this message]
1999-09-23  0:00         ` Hyman Rosen
1999-09-24  0:00           ` Nick Roberts
1999-09-24  0:00             ` Hyman Rosen
1999-09-25  0:00               ` Robert Dewar
1999-09-27  0:00                 ` Hyman Rosen
1999-09-27  0:00                   ` Brian Rogoff
1999-09-28  0:00                   ` Robert Dewar
1999-09-24  0:00         ` Ted Dennison
1999-09-24  0:00           ` Nick Roberts
1999-09-24  0:00         ` Robert Dewar
1999-09-24  0:00           ` Wes Groleau
1999-09-25  0:00             ` Robert Dewar
1999-09-25  0:00             ` Robert Dewar
1999-09-24  0:00       ` Robert Dewar
1999-09-24  0:00     ` Robert Dewar
1999-09-23  0:00 ` Robert I. Eachus
1999-09-24  0:00   ` Nick Roberts
1999-09-25  0:00     ` Robert Dewar
1999-09-25  0:00     ` Robert Dewar
1999-09-25  0:00     ` Robert Dewar
1999-09-27  0:00     ` Ted Dennison
1999-09-27  0:00       ` Pascal Obry
1999-09-28  0:00         ` Ted Dennison
1999-09-28  0:00           ` Robert Dewar
1999-09-29  0:00             ` Geoff Bull
1999-09-28  0:00       ` Robert Dewar
replies disabled

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