comp.lang.ada
 help / color / mirror / Atom feed
* How to loop (elegant) throug a vector ?
@ 2008-06-20 13:19 Reinert Korsnes
  2008-06-20 14:49 ` Pascal Obry
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Reinert Korsnes @ 2008-06-20 13:19 UTC (permalink / raw)


I try to learn to use Ada.Containers. 
Assume the following code:

   package X_t is new Vectors(Positive,Item_t);
   use X_t;
   X : Vector; 

-- I want something more beautiful than this loop:

   for k in 1 .. Positive(X.Length) loop
       do_something(X.Element(k));
   end loop;

Could anybody suggest improvements for the three
last lines in the code?

reinert




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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 13:19 How to loop (elegant) throug a vector ? Reinert Korsnes
@ 2008-06-20 14:49 ` Pascal Obry
  2008-06-20 17:12 ` Returning ranges from a function (was: How to loop (elegant) throug a vector ?) Stefan Bellon
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Pascal Obry @ 2008-06-20 14:49 UTC (permalink / raw)


Reinert Korsnes a �crit :
> Could anybody suggest improvements for the three
> last lines in the code?

A solution using the Iterate routine:

    procedure Do_Something (P : X_t.Cursor) is
       E : constant Item_T := Element (P);
    begin
       ...
    end Do_Something;

    X.Iterate (Do_Something'Access);

Another solution would be to loop using a cursor, something like:

    P : X_t.Cursor := X.First;

    while Has_Element (P) loop
       Do_Something (P);
       Next (P);
       --  With this loop it is possible to exit before the end
       --  exit when <some_condition>;
    end loop;

Both example have not been compiled, so could have some syntax error but 
you get the idea.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|              http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595



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

* Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-20 13:19 How to loop (elegant) throug a vector ? Reinert Korsnes
  2008-06-20 14:49 ` Pascal Obry
@ 2008-06-20 17:12 ` Stefan Bellon
  2008-06-22 14:01   ` Maciej Sobczak
  2008-06-20 19:21 ` How to loop (elegant) throug a vector ? Jeffrey R. Carter
  2008-06-23 17:08 ` Matthew Heaney
  3 siblings, 1 reply; 15+ messages in thread
From: Stefan Bellon @ 2008-06-20 17:12 UTC (permalink / raw)


On Fri, 20 Jun, Reinert Korsnes wrote:

> -- I want something more beautiful than this loop:
> 
>    for k in 1 .. Positive(X.Length) loop
>        do_something(X.Element(k));
>    end loop;

Sorry to high-jack this thread, but I'd like to comment on a somewhat
related topic: For a very long time I was looking for some way to
return a range from a function so that you can do something elegant
like in the following:

   for I in Get_Range loop
      Do_Something (I);
   end loop;

I always thought it to be a deficiency of Ada not being able to return
a range from a function.

A few weeks ago I realised the following solution, which I'd like to
share:

   generic
      type Index_Type is (<>);
   package Generic_Range_Objects is

      type Empty_Component is null record;
      for Empty_Component'Size use 0;

      type Range_Type is array (Index_Type range <>) of Empty_Component;
      pragma Pack (Range_Type);

   end Generic_Range_Objects;

And an instance for Integer ranges ...

   with Generic_Range_Objects;

   package Integer_Range_Objects is new Generic_Range_Objects (Integer);

Now you can do the following:

   function Get_Range
     return Integer_Range_Objects.Range_Type
   is
   begin
      return (42 .. 128 => <>);
   end Get_Range;

And then:

   for I in Get_Range'Range loop
      Do_Something (I);
   end loop;

It's not as elegant as I wished (because of the additional 'Range), but
it is simple and light-weight enough to be usable.

-- 
Stefan Bellon




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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 13:19 How to loop (elegant) throug a vector ? Reinert Korsnes
  2008-06-20 14:49 ` Pascal Obry
  2008-06-20 17:12 ` Returning ranges from a function (was: How to loop (elegant) throug a vector ?) Stefan Bellon
@ 2008-06-20 19:21 ` Jeffrey R. Carter
  2008-06-20 19:48   ` Reinert Korsnes
  2008-06-23 17:11   ` Matthew Heaney
  2008-06-23 17:08 ` Matthew Heaney
  3 siblings, 2 replies; 15+ messages in thread
From: Jeffrey R. Carter @ 2008-06-20 19:21 UTC (permalink / raw)


Reinert Korsnes wrote:
> 
>    for k in 1 .. Positive(X.Length) loop
>        do_something(X.Element(k));
>    end loop;
> 
> Could anybody suggest improvements for the three
> last lines in the code?

for K in 1 .. X.Last_Index loop
    Do_Something (X.Element (K) );
end loop;

Since the correct name for this package is Unbounded_Arrays, it makes sense to 
iterate over it in a manner to iterating over an array.

-- 
Jeff Carter
"C's solution to this [variable-sized array parameters] has real
problems, and people who are complaining about safety definitely
have a point."
Dennis Ritchie
25



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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 19:21 ` How to loop (elegant) throug a vector ? Jeffrey R. Carter
@ 2008-06-20 19:48   ` Reinert Korsnes
  2008-06-20 23:25     ` Jeffrey R. Carter
  2008-06-23 17:14     ` Matthew Heaney
  2008-06-23 17:11   ` Matthew Heaney
  1 sibling, 2 replies; 15+ messages in thread
From: Reinert Korsnes @ 2008-06-20 19:48 UTC (permalink / raw)


Jeffrey R. Carter wrote:

> Reinert Korsnes wrote:
>> 
>>    for k in 1 .. Positive(X.Length) loop
>>        do_something(X.Element(k));
>>    end loop;
>> 
>> Could anybody suggest improvements for the three
>> last lines in the code?
> 
> for K in 1 .. X.Last_Index loop
>     Do_Something (X.Element (K) );
> end loop;
> 
> Since the correct name for this package is Unbounded_Arrays, it makes
> sense to iterate over it in a manner to iterating over an array.
>

Maybe better:

for K in X.First_Index .. X.Last_Index loop
    Do_Something (X.Element (K) );
end loop;

?

Just in case someone in the future change the vector indexing type.
The first element need not correspond to index = 1.

reinert





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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 19:48   ` Reinert Korsnes
@ 2008-06-20 23:25     ` Jeffrey R. Carter
  2008-06-23 17:14     ` Matthew Heaney
  1 sibling, 0 replies; 15+ messages in thread
From: Jeffrey R. Carter @ 2008-06-20 23:25 UTC (permalink / raw)


Reinert Korsnes wrote:
> 
> Maybe better:
> 
> for K in X.First_Index .. X.Last_Index loop
>     Do_Something (X.Element (K) );
> end loop;
> 
> ?
> 
> Just in case someone in the future change the vector indexing type.
> The first element need not correspond to index = 1.

The 1st index is always Index_Type'First. It hasn't been my experience that 
index subtypes change much, but I suppose this is closer to A'range.

-- 
Jeff Carter
"I spun around, and there I was, face to face with a
six-year-old kid. Well, I just threw my guns down and
walked away. Little bastard shot me in the ass."
Blazing Saddles
40



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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-20 17:12 ` Returning ranges from a function (was: How to loop (elegant) throug a vector ?) Stefan Bellon
@ 2008-06-22 14:01   ` Maciej Sobczak
  2008-06-22 18:47     ` Stefan Bellon
  0 siblings, 1 reply; 15+ messages in thread
From: Maciej Sobczak @ 2008-06-22 14:01 UTC (permalink / raw)


On 20 Cze, 19:12, Stefan Bellon <bel...@software-erosion.org> wrote:

> Now you can do the following:
>
>    function Get_Range
>      return Integer_Range_Objects.Range_Type
>    is
>    begin
>       return (42 .. 128 => <>);
>    end Get_Range;
>
> And then:
>
>    for I in Get_Range'Range loop
>       Do_Something (I);
>    end loop;
>
> It's not as elegant as I wished (because of the additional 'Range), but
> it is simple and light-weight enough to be usable.

As far as I can tell, it creates the physical array that might not be
necessarily optimized out by the compiler. You need to store it
somewhere.
It would be nicer to return a "range" that is not dependent on memory
constraints. See xrange in Python.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com



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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-22 14:01   ` Maciej Sobczak
@ 2008-06-22 18:47     ` Stefan Bellon
  2008-06-22 21:06       ` Maciej Sobczak
  0 siblings, 1 reply; 15+ messages in thread
From: Stefan Bellon @ 2008-06-22 18:47 UTC (permalink / raw)


On Sun, 22 Jun, Maciej Sobczak wrote:
> On 20 Cze, 19:12, Stefan Bellon <bel...@software-erosion.org> wrote:

> >    for I in Get_Range'Range loop
> >       Do_Something (I);
> >    end loop;
> >
> > It's not as elegant as I wished (because of the additional 'Range),
> > but it is simple and light-weight enough to be usable.
> 
> As far as I can tell, it creates the physical array that might not be
> necessarily optimized out by the compiler. You need to store it
> somewhere.

You need to store the two words for First and Last (or First and
Length). And indeed, this is what GNAT does. The 'Size of the array
object returned is two words in size.

> It would be nicer to return a "range" that is not dependent on memory
> constraints. See xrange in Python.

I think you cannot get smaller than the two words. The question is
whether this optimisation (for 'Size use 0) can always be guaranteed.

-- 
Stefan Bellon




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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-22 18:47     ` Stefan Bellon
@ 2008-06-22 21:06       ` Maciej Sobczak
  2008-06-23  9:47         ` Stefan Bellon
  0 siblings, 1 reply; 15+ messages in thread
From: Maciej Sobczak @ 2008-06-22 21:06 UTC (permalink / raw)


On 22 Cze, 20:47, Stefan Bellon <bel...@software-erosion.org> wrote:

> You need to store the two words for First and Last (or First and
> Length). And indeed, this is what GNAT does. The 'Size of the array
> object returned is two words in size.

Now I have noticed the for Empty_Component'Size use 0 part. Sorry for
the confusion, but see below for more. :-)

> The question is
> whether this optimisation (for 'Size use 0) can always be guaranteed.

I have a better question: is it *legal*?

Consider 3.6/13:

"A one-dimensional array has a distinct component for each possible
index value."

What does it mean - "distinct"? Doesn't it exclude overlays?

What about "independent addressability" from 13.3? The text is a bit
dense, but I conclude that the 'Size attribute does not have to be
strictly obeyed by the implementation.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com



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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-22 21:06       ` Maciej Sobczak
@ 2008-06-23  9:47         ` Stefan Bellon
  2008-06-23 12:06           ` Maciej Sobczak
  0 siblings, 1 reply; 15+ messages in thread
From: Stefan Bellon @ 2008-06-23  9:47 UTC (permalink / raw)


On Sun, 22 Jun, Maciej Sobczak wrote:

> What about "independent addressability" from 13.3? The text is a bit
> dense, but I conclude that the 'Size attribute does not have to be
> strictly obeyed by the implementation.

I don't think this applies here as the array components are not aliased
and thus there is no need for independent addressability. Perhaps the
compiler should allocate memory for each component as soon as "aliased"
is specified.

But in any case my "range objects" do not rely on the compiler not
allocating memory. This is just a nice and efficient side-effect of the
compiler implementation. So, even if the compiler implementation does
not have to optimise, the semantics of my "range objects" is guaranteed
and for the GNAT implementation it is even optimal concerning memory.

-- 
Stefan Bellon




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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-23  9:47         ` Stefan Bellon
@ 2008-06-23 12:06           ` Maciej Sobczak
  2008-06-23 12:28             ` christoph.grein
  0 siblings, 1 reply; 15+ messages in thread
From: Maciej Sobczak @ 2008-06-23 12:06 UTC (permalink / raw)


On 23 Cze, 11:47, Stefan Bellon <bel...@software-erosion.org> wrote:

> > What about "independent addressability" from 13.3?

> I don't think this applies here as the array components are not aliased

With my version of GNAT everything is stored at the same location when
"aliased" is added to components of the array.
I can see it by having *equal* access variables created from different
array indices:

with Ada.Text_IO;

procedure A is

   type Empty_Record is null record;
   for Empty_Record'Size use 0;

   A : array (Integer range <>) of aliased Empty_Record := (1 .. 100
=> <>);

   type Empty_Ptr is access all Empty_Record;
   P1 : Empty_Ptr := A (1)'Access;
   P2 : Empty_Ptr := A (2)'Access;

begin

   if P1 = P2 then
      Ada.Text_IO.Put_Line ("Equal access values.");
   else
      Ada.Text_IO.Put_Line ("Distinct access values.");
   end if;

end;

Is it bug or feature?

> But in any case my "range objects" do not rely on the compiler not
> allocating memory.

Right, but they just expose an interesting compiler behavior.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com



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

* Re: Returning ranges from a function (was: How to loop (elegant) throug a vector ?)
  2008-06-23 12:06           ` Maciej Sobczak
@ 2008-06-23 12:28             ` christoph.grein
  0 siblings, 0 replies; 15+ messages in thread
From: christoph.grein @ 2008-06-23 12:28 UTC (permalink / raw)


> With my version of GNAT everything is stored at the same location when
> "aliased" is added to components of the array.
> I can see it by having *equal* access variables created from different
> array indices:

But there is nothing to store - Empty_Record'Size = 0, so nothing is
stored in the same location for each index value.

Array object A is nearly empty, it only holds the boundaries. Really
interesting :-)

Note: A compiler need not follow the recommendation to create objects
of zero size. GNAT does because it has to because it claims to
implement all annexes.



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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 13:19 How to loop (elegant) throug a vector ? Reinert Korsnes
                   ` (2 preceding siblings ...)
  2008-06-20 19:21 ` How to loop (elegant) throug a vector ? Jeffrey R. Carter
@ 2008-06-23 17:08 ` Matthew Heaney
  3 siblings, 0 replies; 15+ messages in thread
From: Matthew Heaney @ 2008-06-23 17:08 UTC (permalink / raw)


On Jun 20, 9:19 am, Reinert Korsnes <a...@b.no> wrote:
>    for k in 1 .. Positive(X.Length) loop
>        do_something(X.Element(k));
>    end loop;
>
> Could anybody suggest improvements for the three
> last lines in the code?

for K in X.First_Index .. X.Last_Index loop
   Do_Something (X.Element (K));
end loop;



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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 19:21 ` How to loop (elegant) throug a vector ? Jeffrey R. Carter
  2008-06-20 19:48   ` Reinert Korsnes
@ 2008-06-23 17:11   ` Matthew Heaney
  1 sibling, 0 replies; 15+ messages in thread
From: Matthew Heaney @ 2008-06-23 17:11 UTC (permalink / raw)


On Jun 20, 3:21 pm, "Jeffrey R. Carter"
<spam.jrcarter....@spam.acm.org> wrote:
> Since the correct name for this package is Unbounded_Arrays,

No.  It's a "container".  Implementations are free to use different
non-array implementations.


> it makes sense to
> iterate over it in a manner to iterating over an array.

Like all containers, a vector supports iterating over its elements
using a cursor.  In the unique case of the vector, the container also
supports iteration using an explicit index.



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

* Re: How to loop (elegant) throug a vector ?
  2008-06-20 19:48   ` Reinert Korsnes
  2008-06-20 23:25     ` Jeffrey R. Carter
@ 2008-06-23 17:14     ` Matthew Heaney
  1 sibling, 0 replies; 15+ messages in thread
From: Matthew Heaney @ 2008-06-23 17:14 UTC (permalink / raw)


On Jun 20, 3:48 pm, Reinert Korsnes <a...@b.no> wrote:
>
> for K in X.First_Index .. X.Last_Index loop
>     Do_Something (X.Element (K) );
> end loop;
>
> Just in case someone in the future change the vector indexing type.
> The first element need not correspond to index = 1.

Right.  The first element has index Index_Type'First.

You could also say:

  for K in X.First_Element .. X.Last_Element loop
     Query_Element (X, K, Do_Something'Access);
  end loop;





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

end of thread, other threads:[~2008-06-23 17:14 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-20 13:19 How to loop (elegant) throug a vector ? Reinert Korsnes
2008-06-20 14:49 ` Pascal Obry
2008-06-20 17:12 ` Returning ranges from a function (was: How to loop (elegant) throug a vector ?) Stefan Bellon
2008-06-22 14:01   ` Maciej Sobczak
2008-06-22 18:47     ` Stefan Bellon
2008-06-22 21:06       ` Maciej Sobczak
2008-06-23  9:47         ` Stefan Bellon
2008-06-23 12:06           ` Maciej Sobczak
2008-06-23 12:28             ` christoph.grein
2008-06-20 19:21 ` How to loop (elegant) throug a vector ? Jeffrey R. Carter
2008-06-20 19:48   ` Reinert Korsnes
2008-06-20 23:25     ` Jeffrey R. Carter
2008-06-23 17:14     ` Matthew Heaney
2008-06-23 17:11   ` Matthew Heaney
2008-06-23 17:08 ` Matthew Heaney

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