comp.lang.ada
 help / color / mirror / Atom feed
* How to do it in Ada ?
@ 2001-07-16  3:33 Tomasz Wegrzanowski
  2001-07-16  5:31 ` Jeffrey Carter
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Tomasz Wegrzanowski @ 2001-07-16  3:33 UTC (permalink / raw)


int main(int argc, char **argv)
{
    int *x;
    int n;
    
    n = (argc==1)?1:atoi(argv[1]);
    x = malloc (n*sizeof(int));
    for (x=0;x<n;x++)
	x[i]=0;
    
    /* ... */
}

Something like that ... how to do such dynamic array allocation in Ada ?



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

* Re: How to do it in Ada ?
  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
  2 siblings, 0 replies; 13+ messages in thread
From: Jeffrey Carter @ 2001-07-16  5:31 UTC (permalink / raw)


Tomasz Wegrzanowski wrote:
> 
> int main(int argc, char **argv)
> {
>     int *x;
>     int n;
> 
>     n = (argc==1)?1:atoi(argv[1]);
>     x = malloc (n*sizeof(int));
>     for (x=0;x<n;x++)
>         x[i]=0;
> 
>     /* ... */
> }
> 
> Something like that ... how to do such dynamic array allocation in Ada ?

The simple answer is, you don't. Ada makes this kind of thing much
simpler and less error-prone than in a low-level language.

procedure The_Right_Way is
   type List is array (Positive range <>) of Integer;

   function Get return Positive is separate;

   Num_Integers : constant Positive := Get;

   X : List (1 .. Num_Integers) := (others => 0);
begin -- The_Right_Way
   ...
end The_Right_Way;

Note that everything in your example is done in the declarative part.

-- 
Jeff Carter
"Nobody expects the Spanish Inquisition!"
Monty Python's Flying Circus



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

* Re: How to do it in Ada ?
  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
  2 siblings, 0 replies; 13+ messages in thread
From: Al Christians @ 2001-07-16  6:41 UTC (permalink / raw)


with Ada.Text_IO;
with Ada.Command_Line;
procedure Initialize_Array is

   A:  Array(1..Integer'Value(Ada.Command_Line.Argument(1))) 
         of Integer := ( Others => 0 );
   begin
      -- The array is already initialized
      -- The following statements just show that it is
      Ada.Text_IO.Put( "First =" & Integer'Image(A'First));
      Ada.Text_IO.Put( "  First Value =" & Integer'Image(A(A'First)));
      Ada.Text_IO.Put( "  Last =" & Integer'Image(A'Last));
      Ada.Text_IO.Put( "  Last Vale=" & Integer'Image(A(A'Last)));
   end;      


Tomasz Wegrzanowski wrote:
> 
> int main(int argc, char **argv)
> {
>     int *x;
>     int n;
> 
>     n = (argc==1)?1:atoi(argv[1]);
>     x = malloc (n*sizeof(int));
>     for (x=0;x<n;x++)
>         x[i]=0;
> 
>     /* ... */
> }
> 
> Something like that ... how to do such dynamic array allocation in Ada ?



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

* Re: How to do it in Ada ?
  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
  2001-07-16 17:37   ` Ken Garlington
  2 siblings, 2 replies; 13+ messages in thread
From: tmoran @ 2001-07-16  6:51 UTC (permalink / raw)


> int main(int argc, char **argv)
> {
>     int *x;
>     int n;
>
>     n = (argc==1)?1:atoi(argv[1]);
>     x = malloc (n*sizeof(int));
>     for (x=0;x<n;x++)
>         x[i]=0;
>
>     /* ... */
> }

The most natural Ada way is:

with Ada.Command_Line;
procedure Main is
  N : Integer;
begin
  if Ada.Command_Line.Argument_Count = 0 then N := 1;
  else N := Integer'value(Ada.Command_Line.Argument(1));
  end if;
  declare
    X : array(1 .. N) of Integer := (others=>0);
  begin
    ....
  end;
end Main;

> Something like that ... how to do such dynamic array allocation in Ada ?
  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;
  type Px_Type is access X_Array_Type;
  X : Px_Type;
begin
  if Ada.Command_Line.Argument_Count = 0 then N := 1;
  else N := Integer'value(Ada.Command_Line.Argument(1));
  end if;
  X := new X_Array_Type'((1 .. N => 0));
    ....
end Main;



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

* Re: How to do it in Ada ?
  2001-07-16  6:51 ` tmoran
@ 2001-07-16 16:56   ` Mark Lundquist
  2001-07-16 18:42     ` Nonsense (was Re: How to do it in Ada ?) Mark Lundquist
                       ` (2 more replies)
  2001-07-16 17:37   ` Ken Garlington
  1 sibling, 3 replies; 13+ messages in thread
From: Mark Lundquist @ 2001-07-16 16:56 UTC (permalink / raw)



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






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

* Re: How to do it in Ada ?
  2001-07-16  6:51 ` tmoran
  2001-07-16 16:56   ` Mark Lundquist
@ 2001-07-16 17:37   ` Ken Garlington
  1 sibling, 0 replies; 13+ messages in thread
From: Ken Garlington @ 2001-07-16 17:37 UTC (permalink / raw)


Heck, if I were going to do it the natural Ada way, I'd say:

with Ada.Command_Line;
with Ada.Text_Io; -- for debug only
procedure Main is

   -- N is the first argument, if it is specified and "reasonable".
   -- Otherwise, it defaults to the value 1 (one array element).
   function N return Positive is
      subtype OK_Range is Positive range 1 .. 65_535;
      -- 65,535 can be replaced with whatever is "reasonable"
      -- for an upper limit, or the range eliminated altogether.
   begin
      return OK_Range'Value(Ada.Command_Line.Argument(1));
   exception
      when others =>
         return 1;
   end N;

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

begin

   Ada.Text_Io.Put_Line("Hey! You've got an array of" &
      Natural'Image(X'Length) & " element(s)!");

   -- do what you gotta do

end Main;





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

* Nonsense (was Re: How to do it in Ada ?)
  2001-07-16 16:56   ` Mark Lundquist
@ 2001-07-16 18:42     ` Mark Lundquist
  2001-07-16 22:20       ` Jeffrey Carter
                         ` (2 more replies)
  2001-07-16 22:18     ` How to do it in Ada ? Jeffrey Carter
  2001-07-20  5:39     ` David Thompson
  2 siblings, 3 replies; 13+ messages in thread
From: Mark Lundquist @ 2001-07-16 18:42 UTC (permalink / raw)



I <up.yerz@nospam.com> wrote nonsense in message
news:P0F47.357734$p33.7248200@news1.sttls1.wa.home.com...
>
>[snip]
>
> Alternatively, the declaration could be written this way:
>
>     X := new X_Array_Type (1 .. N) := (others => 0);
>

What a bunch of crap!  I can't belive I wrote that.  It must have been
before my first cup of coffee this morning.  Or, I started writing that line
and then went away, and then came back and blew a brain fuse when I resumed
typing.  Maybe when I went away, it was to get the cup of coffee!

What one *could* write (not that you'd want to, but it illustrates the
language concept I was trying to highlight), is:

    X : new X_Array_Type (1 .. N);

    begin
            X := (others => 0);
            .
            .

Doh!  Sheesh...
-- mark






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

* Re: How to do it in Ada ?
  2001-07-16 16:56   ` Mark Lundquist
  2001-07-16 18:42     ` Nonsense (was Re: How to do it in Ada ?) Mark Lundquist
@ 2001-07-16 22:18     ` Jeffrey Carter
  2001-07-17  4:06       ` tmoran
  2001-07-20  5:39     ` David Thompson
  2 siblings, 1 reply; 13+ messages in thread
From: Jeffrey Carter @ 2001-07-16 22:18 UTC (permalink / raw)


Mark Lundquist wrote:
> 
> >   X := new X_Array_Type'((1 .. N => 0));
> 
> What about those double parenthesis... do those look funny?  Well, they
> really are required.

This is incorrect. The syntax for a qualified expression is

qualified_expression ::=
        subtype_mark'(expression) | subtype_mark'aggregate

so the double parens are not required.

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

This is also incorrect.

-- 
Jeffrey Carter



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

* Re: Nonsense (was Re: How to do it in Ada ?)
  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
  2 siblings, 0 replies; 13+ messages in thread
From: Jeffrey Carter @ 2001-07-16 22:20 UTC (permalink / raw)


Mark Lundquist wrote:
> 
> I <up.yerz@nospam.com> wrote nonsense in message
> news:P0F47.357734$p33.7248200@news1.sttls1.wa.home.com...
> >
> >[snip]
> >
> > Alternatively, the declaration could be written this way:
> >
> >     X := new X_Array_Type (1 .. N) := (others => 0);
> >
> 
> What a bunch of crap!  I can't belive I wrote that.

I'm glad you realize this is incorrect. However, ...

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

this is also incorrect. You could write

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

-- 
Jeffrey Carter



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

* Re: Nonsense (was Re: How to do it in Ada ?)
  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
  2 siblings, 0 replies; 13+ messages in thread
From: Ken Garlington @ 2001-07-17  0:13 UTC (permalink / raw)



"Mark Lundquist" <up.yerz@nospam.com> wrote in message
news:yAG47.358161$p33.7256533@news1.sttls1.wa.home.com...
:
: I <up.yerz@nospam.com> wrote nonsense in message
: news:P0F47.357734$p33.7248200@news1.sttls1.wa.home.com...
: >
: >[snip]
: >
: > Alternatively, the declaration could be written this way:
: >
: >     X := new X_Array_Type (1 .. N) := (others => 0);
: >
:
: What a bunch of crap!  I can't belive I wrote that.  It must have been
: before my first cup of coffee this morning.  Or, I started writing that
line
: and then went away, and then came back and blew a brain fuse when I
resumed
: typing.  Maybe when I went away, it was to get the cup of coffee!
:
: What one *could* write (not that you'd want to, but it illustrates the
: language concept I was trying to highlight), is:
:
:     X : new X_Array_Type (1 .. N);
:
:     begin
:             X := (others => 0);

This still looks a little off... perhaps you meant something like

package X_Array is

   type Object is array (Positive range <>) of Integer;
   type Object_Access is access Object;
   function New_Object_Access return Object_Access;

end X_Array;

package body X_Array is

  function N return Positive is... (see other post)

   function New_Object_Access return Object_Access is
     X : Object_Access := new Object(1 .. N);
   begin
     X.all := (others => 0);
     return X;
   end New_Object_Access;

end X_Array;





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

* Re: Nonsense (was Re: How to do it in Ada ?)
  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
  2 siblings, 0 replies; 13+ messages in thread
From: Robert Dewar @ 2001-07-17  3:53 UTC (permalink / raw)


"Mark Lundquist" <up.yerz@nospam.com> wrote in message news:<yAG47.358161$p33.7256533@news1.sttls1.wa.home.com>...
> What one *could* write (not that you'd want to, but it illustrates 
> the language concept I was trying to highlight), is:
> 
>     X : new X_Array_Type (1 .. N);
> 
>     begin
>             X := (others => 0);
>             .
>             .


I am sure others will point out that this is also incorrect. As I
have suggested in the past, I strongly advise that if people post
Ada code, they compile it and make sure it works, and then cut
and paste actual working code. This will help avoid spreading
misinformation. This is good advice for anyone, no matter how
well you think you know Ada. I certainly do it for any code I
post, it is too easy to make a silly typo, and end up confusing
people if you do not take the trouble to make sure that code you
post is correct.



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

* Re: How to do it in Ada ?
  2001-07-16 22:18     ` How to do it in Ada ? Jeffrey Carter
@ 2001-07-17  4:06       ` tmoran
  0 siblings, 0 replies; 13+ messages in thread
From: tmoran @ 2001-07-17  4:06 UTC (permalink / raw)


> qualified_expression ::=
>         subtype_mark'(expression) | subtype_mark'aggregate
>
> so the double parens are not required.
  Learn something new every day!  :)

It's interesting to see the variety of people's answers to the question.



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

* Re: How to do it in Ada ?
  2001-07-16 16:56   ` Mark Lundquist
  2001-07-16 18:42     ` Nonsense (was Re: How to do it in Ada ?) Mark Lundquist
  2001-07-16 22:18     ` How to do it in Ada ? Jeffrey Carter
@ 2001-07-20  5:39     ` David Thompson
  2 siblings, 0 replies; 13+ messages in thread
From: David Thompson @ 2001-07-20  5:39 UTC (permalink / raw)


Mark Lundquist <up.yerz@nospam.com> wrote :
...
> 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 recent revision C99 added, and gcc/GNU-C has long implemented
as an extension, "auto" arrays and array types with bounds computed
effectively at elaboration (although they don't call it that), somewhat
unimaginatively called Variable Length Arrays.
(They are still 0-based and not bounds-checked.)

>     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.

For a declared array in C, you can write an initializer which specifies
only some, at minimum one, element(s), and all unspecified elements
are initialized to 0 (or floating 0.0 or pointer NULL).  In C99 you can
select arbitrary elements using a Designated Initializer:
  int foo[10] = { [1] = 3, [7] = 4 }; /* [0,2..6,8,9] = 0 */
but you cannot use ranges (3..5 => 42) or have the "remainder"
(others =>) case be anything other than "zero" as above.

malloc'ed space is not initialized, except that by using calloc
instead you can have it initialized to all-zero-BITS; this is not
guaranteed to produce integer 0, floating 0.0, or pointer NULL,
with the single exception of the type unsigned char, though
on most if not all "normal" systems it does.  Also on many
popular current OSes all memory not explicitly (statically) loaded
is initialized to zero-bits, including not-yet-used stack and heap,
but to use this "safely" you must have control over all the code in
your process from main down and even then it's easy to get wrong.

Also new in C99 you can write a Compound Literal for an array or struct.
But arrays still aren't first-class; you can't assign any array value,
including such a literal, to an array object/variable, malloc'ed or not.
You can memcpy() it, but this is easier to mess up.

> 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.
>
Well, even if you write the loop, a good compiler can optimize it
to something better.  The important gain is source clarity.

--
- David.Thompson 1 now at worldnet.att.net








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

end of thread, other threads:[~2001-07-20  5:39 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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
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

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