comp.lang.ada
 help / color / mirror / Atom feed
From: "Mark Lundquist" <up.yerz@nospam.com>
Subject: Re: How to do it in Ada ?
Date: Mon, 16 Jul 2001 16:56:15 GMT
Date: 2001-07-16T16:56:15+00:00	[thread overview]
Message-ID: <P0F47.357734$p33.7248200@news1.sttls1.wa.home.com> (raw)
In-Reply-To: Z9w47.213303$%i7.122829537@news1.rdc1.sfba.home.com


I'd like to comment on Tom Moran's example, to highlight some Ada concepts
for the benefit of the original poster and any other newbies who might be
interested...

In Tom's first example, all the important stuff is in this line:

    X : array(1 .. N) of Integer := (others=>0);

Things to note:

    1) No heap allocation is required.  In C, the size in an array
declaration _has_ to be static.  So in the original C example, the use of
malloc() is necessitated by the fact that we don't know at compile time how
many elements the array will have.  In Ada, you can declare an object with a
non-static constraint.  The language doesn't specify where the array in this
example will be allocated from.  Concepts like "stack" and "heap" are
implementation-specifics; the Ada language definition is at a more abstract
level.  However, virtually all Ada compilers will allocate this array on the
stack (they might go to the heap for a sufficiently large array).  So, not
only is there no pointer stuff or allocation stuff in the syntax, but for an
array of sufficiently small size there is also no "behind the scenes" heap
allocation -- it's going to happen on the stack, so (a) it's more efficient
and (b) you don't have to remember to free it.
    2) The "(others => 0)" thing is called an aggregate.  Aggregates are to
composite types (arrays and records) what literals are to elementary types,
so you can use an aggregate to initialize an object of a composite type.  So
for arrays, there is no need to code an iteration across the array elements.
Not only does this mean that you're programming at a higher level of
abstraction, it leaves freedom for the compiler to do it more efficiently,
if the compiler knows a better way then elementwise iteration.

>   If you mean heap allocation, not just dynamic stack allocation,
> then:
>
> with Ada.Command_Line;
> procedure Main is
>   N : Integer;
>   type X_Array_Type is array(Integer range <>) of Integer;
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^

This defines what is called an "unconstrained type".  The meaning is that an
object of the type might have bounds given by any particular integer range.
So the following object declarations are all valid:

    A : X_Array_Type (1 .. 20);
    B : X_Array_Type (0 .. 5);
    C : X_Array_Type (17 .. 33);
    D : X_Array_Type (-7 .. 13);

Saying "Natural range <>" or "Positive range <>" would impose more
requirements on legal index ranges (Natural and Positive are subtypes of
Integer).  It's a good idea to use Natural or Positive whenever possible to
express your intent, not just use Integer for everything.  (I know some
people say that you shouldn't use any of them, but always define your own
integer types... I don't really want to open that argument back up right
now... :-)  But I think everyone would agree that you shouldn't use Integer
if you don't expect or intend negative values.

Objects of an unconstrained array type have fixed bounds, but the bounds are
established where the object is declared (not the type).  (There's also a
special case called an "unconstrained object", but that's beyond the scope
of this lesson :-).

By contranst, a constrained type (or constrained subtype) has the index
range "built in":

    type A_Constrained_Array_Type is array (Positive range 1 .. 10) of
Whatever;

All objects of this type will have index range 1..10.

In Tom's example, the reason for declaring this type is that the access type
definition that follows requires a name for the "designated type":

>   type Px_Type is access X_Array_Type;

To create the initialized object, he does this:

>   X := new X_Array_Type'((1 .. N => 0));

What about those double parenthesis... do those look funny?  Well, they
really are required.  The inner set of parens and their contents, "(1..N =>
0)" is the aggregate, like in the earlier example that used "others".  The
outer set of parens is part of something (" X_Array_Type'(...) ") called a
"qualified expression" (qualified by the name of its type).  So they aren't
like parens in mathematical notation -- you can't collapse them.

Could he have used "others" instead of  "1 .. N" in that example?  Not the
way he wrote it... try writing "others" in the place of "1 .. N", and
there's no longer an "N" anywhere in the declaration, i.e. Ada has no way of
knowing that you want the array to be N things big!

Alternatively, the declaration could be written this way:

    X := new X_Array_Type (1 .. N) := (others => 0);

That is, constrain the subtype first, then you can use the "others" notation
now that the constraints are established.

Hope this helps somebody... I think it's always a good thing when you can
pull out some concepts, as opposed to just having a "recipe" for writing an
equivalent Language X code fragment in Language Y :-)...

-- Mark






  reply	other threads:[~2001-07-16 16:56 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-07-16  3:33 How to do it in Ada ? Tomasz Wegrzanowski
2001-07-16  5:31 ` Jeffrey Carter
2001-07-16  6:41 ` Al Christians
2001-07-16  6:51 ` tmoran
2001-07-16 16:56   ` Mark Lundquist [this message]
2001-07-16 18:42     ` Nonsense (was Re: How to do it in Ada ?) Mark Lundquist
2001-07-16 22:20       ` Jeffrey Carter
2001-07-17  0:13       ` Ken Garlington
2001-07-17  3:53       ` Robert Dewar
2001-07-16 22:18     ` How to do it in Ada ? Jeffrey Carter
2001-07-17  4:06       ` tmoran
2001-07-20  5:39     ` David Thompson
2001-07-16 17:37   ` Ken Garlington
replies disabled

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