comp.lang.ada
 help / color / mirror / Atom feed
* Ada2012 : In praise of 'for ... of ... loop'...
@ 2012-05-29 14:29 Martin
  2012-05-29 15:02 ` Georg Bauhaus
  0 siblings, 1 reply; 14+ messages in thread
From: Martin @ 2012-05-29 14:29 UTC (permalink / raw)


This addition to Ada is brilliant...I've just been refactoring some Ada05 into Ada2012 and this just makes the code so much clearer! No more nested subprograms (of nested subprograms (of nested ...)).

-- Martin



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-29 14:29 Ada2012 : In praise of 'for ... of ... loop' Martin
@ 2012-05-29 15:02 ` Georg Bauhaus
  2012-05-30  8:10   ` Martin
  0 siblings, 1 reply; 14+ messages in thread
From: Georg Bauhaus @ 2012-05-29 15:02 UTC (permalink / raw)


On 29.05.12 16:29, Martin wrote:
> This addition to Ada is brilliant...I've just been refactoring some Ada05 into Ada2012 and this just makes the code so much clearer! No more nested subprograms (of nested subprograms (of nested ...)).
> 
> -- Martin

Could you illustrate a bit? How much of the clarity is caused, if
so, by being shorter, using assignment in place of nested subprograms,
reducing the number of names, or ...



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-29 15:02 ` Georg Bauhaus
@ 2012-05-30  8:10   ` Martin
  2012-05-30  8:15     ` Thomas Løcke
                       ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Martin @ 2012-05-30  8:10 UTC (permalink / raw)


On Tuesday, May 29, 2012 4:02:47 PM UTC+1, Georg Bauhaus wrote:
> On 29.05.12 16:29, Martin wrote:
> > This addition to Ada is brilliant...I've just been refactoring some Ada05 into Ada2012 and this just makes the code so much clearer! No more nested subprograms (of nested subprograms (of nested ...)).
> > 
> > -- Martin
> 
> Could you illustrate a bit? How much of the clarity is caused, if
> so, by being shorter, using assignment in place of nested subprograms,
> reducing the number of names, or ...

Here's a very small example... what we have now:
   procedure Save (This                    : in out Configuration;
                   Filename                :        String;
                   Header_Comments         :        String_Vectors.Vector := String_Vectors.Empty_Vector;
                   Include_Last_Saved_Time :        Boolean               := False) is
      use type String_Vectors.Vector;
      File : File_Type;
   begin
      begin
         Create (File, Out_File, Filename);
      exception
         when others =>
            Open (File, Out_File, Filename);
      end;
      for Comment of Header_Comments loop
         Put_Line (File, Comment_Str & Comment);
      end loop;
      if Include_Last_Saved_Time then
         Put_Line (File, Comment_Str & "Last saved: " & Image (Date => Clock));
      end if;
      for Section of This.Sections loop
         Put_Line (File, "[" & To_String (Section.Name) & "]");
         for Pair of Section.Pairs loop
            Put_Line (File, To_String (Pair.Key) & "=" & To_String (Pair.Value));
         end loop;
      end loop;
      Close (File);
   exception
      -- implementation detail
   end Save;





what we used to have (mocked up!):

   procedure Save (This                    : in out Configuration;
                   Filename                :        String;
                   Header_Comments         :        String_Vectors.Vector := String_Vectors.Empty_Vector;
                   Include_Last_Saved_Time :        Boolean               := False) is
      use type String_Vectors.Vector;
      File : File_Type;

      -----------
      -- Write --
      -----------

      procedure Write (C : Section_Vectors.Cursor) is

         -------------------
         -- Write_Comment --
         -------------------

         procedure Write_Comment (C : String_Vectors.Cursor) is
         begin
            Put_Line (File, Comment_Str & String_Vectors.Element (C));
         end Write_Comment;

         -----------
         -- Write --
         -----------

         procedure Write (C : Key_Value_Pair_Vectors.Cursor) is
            Pair : constant Key_Value_Pair := Key_Value_Pair_Vectors.Element (C);
         begin
            Put_Line (File, To_String (Pair.Key) & "=" & To_String (Pair.Value));
         end Write;

         This_Section : constant Section := Section_Vectors.Element (C);
      begin
         Put_Line (File, "[" & To_String (This_Section.Name) & "]");
         This_Section.Pairs.Iterate (Write'Access);
      end Write;
         
   begin
      begin
         Create (File, Out_File, Filename);
      exception
         when others =>
            Open (File, Out_File, Filename);
      end;
      Header_Comments.Iterator (Write_Comment'Access);
      if Include_Last_Saved_Time then
         Put_Line (File, Comment_Str & "Last saved: " & Image (Date => Clock));
      end if;
      This.Sections.Iterate (Write'Access);
      Close (File);
   exception
      -- implementation detail
   end Save;

That's 54 lines down to 29 lines, no 'Access and it's perfectly clear what's happening and it happens in a single subprogram. No need to talk about Cursor or calls to Element (C)...

...It also enhances the value of other nested subprograms - they're probably doing something more interesting, so I don't mind the comment-box headers for them as much as I used to.

All thanks to a little syntatic sugar.

To my eyes, this a big win.

-- Martin



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30  8:10   ` Martin
@ 2012-05-30  8:15     ` Thomas Løcke
  2012-05-30 16:21       ` Pascal Obry
  2012-05-30 19:30     ` Jeffrey Carter
  2012-05-30 22:26     ` Georg Bauhaus
  2 siblings, 1 reply; 14+ messages in thread
From: Thomas Løcke @ 2012-05-30  8:15 UTC (permalink / raw)


On 05/30/2012 10:10 AM, Martin wrote:
> To my eyes, this a big win.


I agree. The new way is a lot more readable. At least to me.

Very nice indeed.  :o)

-- 
Thomas L�cke | thomas@12boo.net | http://12boo.net



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30  8:15     ` Thomas Løcke
@ 2012-05-30 16:21       ` Pascal Obry
  0 siblings, 0 replies; 14+ messages in thread
From: Pascal Obry @ 2012-05-30 16:21 UTC (permalink / raw)



Thomas,

> I agree. The new way is a lot more readable. At least to me.
> 
> Very nice indeed.  :o)

Quite yes! I think this is one of the best new feature of Ada 2012, I do
expect to use it in AWS when it is stable enough in GNAT GPL. I will
simplify some units for sure.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|    http://www.obry.net  -  http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B




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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30  8:10   ` Martin
  2012-05-30  8:15     ` Thomas Løcke
@ 2012-05-30 19:30     ` Jeffrey Carter
  2012-05-30 20:54       ` Pascal Obry
  2012-05-31 14:09       ` Martin
  2012-05-30 22:26     ` Georg Bauhaus
  2 siblings, 2 replies; 14+ messages in thread
From: Jeffrey Carter @ 2012-05-30 19:30 UTC (permalink / raw)


On 05/30/2012 01:10 AM, Martin wrote:
>
>        for Comment of Header_Comments loop
>           Put_Line (File, Comment_Str&  Comment);
>        end loop;
>        if Include_Last_Saved_Time then
>           Put_Line (File, Comment_Str&  "Last saved: "&  Image (Date =>  Clock));
>        end if;
>        for Section of This.Sections loop
>           Put_Line (File, "["&  To_String (Section.Name)&  "]");
>           for Pair of Section.Pairs loop
>              Put_Line (File, To_String (Pair.Key)&  "="&  To_String (Pair.Value));
>           end loop;
>        end loop;

This uses 2 inline "for" loops, one containing a nested "for loop".

>        Close (File);
>     exception
>        -- implementation detail
>     end Save;
>
> what we used to have (mocked up!):

This uses vector iterators.

While this is a nice feature, I don't think it's worth the added language 
complexity.

In general, using "for" loops will be clearer than using iterators. In the case 
of vectors (or unbounded arrays, to use their correct name), one can iterate 
over them using "for" loops, and the use of iterators for an array abstraction 
is a questionable practice:

for I in Header_Comments.First_Index .. Header_Comments.Last_Index loop
    Put_Line (File, Comment_Str & Header_Comments.Element (I) );
end loop;

if ... then
    ...
end if;

for I in This.Sections.First_Index .. This.Sections.Last_Index loop
    Section := This.Sections.Element (I);
    Put_Line ...

    for J in Section.Pairs.First_Index .. Section.Pairs.Last_Index loop
       Pair := Section.Pairs.Element (J);
       Put_Line ...
    end loop;
end loop;

I think this is equally clear and requires no additional language complexity.

Had your example used sets or maps it would have been a stronger argument.

-- 
Jeff Carter
"He didn't get that nose from playing ping-pong."
Never Give a Sucker an Even Break
110

--- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net ---



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30 19:30     ` Jeffrey Carter
@ 2012-05-30 20:54       ` Pascal Obry
  2012-05-31 14:09       ` Martin
  1 sibling, 0 replies; 14+ messages in thread
From: Pascal Obry @ 2012-05-30 20:54 UTC (permalink / raw)



Jeffrey,

> This uses vector iterators.
> 
> While this is a nice feature, I don't think it's worth the added
> language complexity.

No I think you missed one point. In the case of:

   for Item of <array or containers> loop
     ...
   end loop;

Item can be read and written in-place. This can be achieved currently
without a callback.

Pascal.

-- 

--|------------------------------------------------------
--| Pascal Obry                           Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--|    http://www.obry.net  -  http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B




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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30  8:10   ` Martin
  2012-05-30  8:15     ` Thomas Løcke
  2012-05-30 19:30     ` Jeffrey Carter
@ 2012-05-30 22:26     ` Georg Bauhaus
  2012-05-30 22:45       ` Georg Bauhaus
  2012-06-07  0:19       ` Randy Brukardt
  2 siblings, 2 replies; 14+ messages in thread
From: Georg Bauhaus @ 2012-05-30 22:26 UTC (permalink / raw)


On 30.05.12 10:10, Martin wrote:

> That's 54 lines down to 29 lines, no 'Access and it's perfectly clear what's happening and it happens in a single subprogram. No need to talk about Cursor or calls to Element (C)...
>
> ...It also enhances the value of other nested subprograms - they're probably doing something more interesting, so I don't mind the comment-box headers for them as much as I used to.
>
> All thanks to a little syntatic sugar.
>
> To my eyes, this a big win.

To my eyes also. It is really nice that Iterate and the "loop
body subprograms" are not torn apart. That seems to outweigh
the loss of naming opportunities.


I'm still unsure if sweetening adds clarity when one has to write for
"the other side" of syntax sugar. For example, when providing a
concrete Forward_Iterator from Ada.Iterator_Interfaces.
However, because writing a Forward_Iterator seems to require more
types (and packaging) in place of juggling subprograms from the
container types, that might be a win too, even at the price of
added LOC.

As an example, I have tried a "functional" Reduce function written in
2005 style and in 2012 style, special in that it is required to
operate on a span of the values only, not the whole container,
mimicking Floor and Ceiling. In pseudo code,

   "+"/(First .. Last),

While the 2012 version of Reduce is pleasantly clear and a little shorter,
writing the "backstage stuff" had, at first, seemed to spoil the effort.

In Ada 2012, there is an Iterate function in the 2012 Vectors that
takes a parameter Start : Cursor, but not a corresponding Finish : Cursor.

So I made a Forward_Iterator that would know Start and Finish.
It has a construction function and overriding First and Next.
This  made the whole program quite a bit longer.
Not necessarily worse, I think, but longer.
Perhaps more "rigorous", or "typish"?

I hope the any unnecessary lengthening is caused by my limited
understanding. Or that the type centric approach of 2012 Forward_Iterator
is better, more clear, and more modular in the end.


Package Iterations_05 below is the 2005 version of the Reduce part.
I think the approach follows standard STL style programming.

generic
    type Element_Type is private;
    type Cursor is private;
    with function Next (Position : Cursor) return Cursor is <>;
    with function Element (Position : Cursor) return Element_Type is <>;
package Iterations_05 is

    generic
       Zero : in Element_Type;
       with function Binop (Left, Right : in Element_Type) return Element_Type;
    function Reduce_05 (First, One_After : Cursor) return Element_Type;

end Iterations_05;


package body Iterations_05 is

    function Reduce_05 (First, One_After : Cursor) return Element_Type is
       Result : Element_Type;
       Position : Cursor;
    begin
       Result := Zero;
       Position := First;
       loop
          exit when Position = One_After;
          Result := Binop (Result, Element (Position));
          Position := Next (Position);
       end loop;
       return Result;
    end Reduce_05;

end Iterations_05;


After instantiating the two generics, one picks cursors for the
endpoints of the "intervals" to be taken from a container.
(At 1 and 50, and 51 and 100 in this case.)

with Ada.Text_IO;
with Iterations_05;
with Num_Types, Num_Vecs;
procedure Test_Iterations_05 is

    use Num_Vecs;

    package Functional is new Iterations_05
      (Element_Type => Num_Types.Nat,
       Cursor => Num_Vecs.Cursor);

    use type Num_Types.Nat;

    function Sum is new Functional.Reduce_05
      (Zero => 0,
       Binop => "+");

    package Num_IO is new Ada.Text_IO.Integer_IO (Num_Types.Nat);

    List : Num_Vecs.Vector;
begin
    for K in Num_Types.Nat range 1 .. 100 loop
       List.Append (K);
    end loop;
    Num_IO.Put (Sum (First     => First (List),
                     One_After => Next (To_Cursor (List,  50))));
    Num_IO.Put (Sum (First     => To_Cursor (List, 51),
                     One_After => Next (Last (List))));
end Test_Iterations_05;


That's it.

The 2012 version of the "functional" part Iterations_2012 is just a little
shorter than its 2005 counterpart. The body of the Reduce function
uses a sweetened for loop:


with Ada.Iterator_Interfaces;
generic
    type Element_Type is private;
    with package Iteration is new Ada.Iterator_Interfaces (<>);
    with function Element (Position : Iteration.Cursor) return Element_Type;
package Iterations_2012 is

    generic
       Zero : in Element_Type;
       with function Binop (Left, Right : in Element_Type) return Element_Type;
    function Reduce_2012 (Span : Iteration.Forward_Iterator'class) return Element_Type;

end Iterations_2012;


package body Iterations_2012 is

    function Reduce_2012 (Span : Iteration.Forward_Iterator'class) return Element_Type is
       Result : Element_Type;
    begin
       Result := Zero;
       for k in Span loop
          Result := Binop (Result, Element (k));
       end loop;
       return Result;
    end Reduce_2012;

end Iterations_2012;


Since a sweetened for loop should be used, I though that passing a "slice"
of a container could only be achieved by a Forward_Iterator. Is this correct?
Note the lengthy package called Splitting that provides it.


with Ada.Iterator_Interfaces;
with Num_Types, Num_Vecs;
with Iterations_2012;
with Ada.Text_IO;
procedure Test_Iterations_2012 is

    use Num_Vecs;
    
    package Split_Iterators is new Ada.Iterator_Interfaces
      (Cursor => Num_Vecs.Cursor,
       Has_Element => Num_Vecs.Has_Element);
    
    package Splitting is
       use Split_Iterators;
    
       type Split_Iterator is
	 limited new Split_Iterators.Forward_Iterator with
	 record
	   First, One_After : Num_Vecs.Cursor;
	 end record;
    
       function Make_Iterator
         (First, One_After : Num_Vecs.Cursor) return Split_Iterator;
       overriding function First (Object : Split_Iterator) return Cursor;
       overriding function Next
	(Object : Split_Iterator; Position: Cursor) return Cursor;
    end Splitting;
    
    package body Splitting is
       function Make_Iterator
	(First, One_After : Num_Vecs.Cursor) return Split_Iterator is
       begin
	 return (Split_Iterators.Forward_Iterator with First, One_After);
       end Make_Iterator;
       
       overriding function First (Object : Split_Iterator) return Cursor is
       begin
	 return Object.First;
       end First;
    
       overriding function Next
	(Object : Split_Iterator; Position: Cursor) return Cursor is
       begin
	 if Position = Object.One_After then
	    return Num_Vecs.No_Element;
	 else
	    return Num_Vecs.Next (Position);
	 end if;
       end Next;
    end Splitting;
    
    package Functional is new Iterations_2012
      (Element_Type => Num_Types.Nat,
       Element => Num_Vecs.Element,
       Iteration => Split_Iterators);

    use type Num_Types.Nat;

    function Sum is new Functional.Reduce_2012
      (Zero => 0,
       Binop => "+");

    package Num_IO is new Ada.Text_IO.Integer_IO (Num_Types.Nat);

    List : Num_Vecs.Vector;
begin
    for K in Num_Types.Nat range 1 .. 100 loop
       List.Append (K);
    end loop;
      
    Num_IO.Put (Sum (Splitting.Make_Iterator
       (First     => First (List),
       One_After => Next (To_Cursor (List,  50)))));

    Num_IO.Put (Sum ( Splitting.Make_Iterator
       (First     => To_Cursor (List, 51),
       One_After => Next (Last (List)))));
end Test_Iterations_2012;


Is Splitting written in the way we should, when using Ada 2012?



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30 22:26     ` Georg Bauhaus
@ 2012-05-30 22:45       ` Georg Bauhaus
  2012-06-07  0:19       ` Randy Brukardt
  1 sibling, 0 replies; 14+ messages in thread
From: Georg Bauhaus @ 2012-05-30 22:45 UTC (permalink / raw)


More than 40 years of c&p and it remains a hurdle. Sorry.

    package Split_Iterators is new Ada.Iterator_Interfaces
      (Cursor => Num_Vecs.Cursor,
       Has_Element => Num_Vecs.Has_Element);

    package Splitting is
       use Split_Iterators;

       type Split_Iterator is
          limited new Split_Iterators.Forward_Iterator with
          record
            First, One_After : Num_Vecs.Cursor;
          end record;

       function Make_Iterator
         (First, One_After : Num_Vecs.Cursor) return Split_Iterator;
       overriding function First (Object : Split_Iterator) return Cursor;
       overriding function Next
         (Object : Split_Iterator; Position: Cursor) return Cursor;
    end Splitting;

    package body Splitting is
       function Make_Iterator
         (First, One_After : Num_Vecs.Cursor) return Split_Iterator is
       begin
          return (Split_Iterators.Forward_Iterator with First, One_After);
       end Make_Iterator;

       overriding function First (Object : Split_Iterator) return Cursor is
       begin
          return Object.First;
       end First;

       overriding function Next
         (Object : Split_Iterator; Position: Cursor) return Cursor is
       begin
          if Position = Object.One_After then
             return Num_Vecs.No_Element;
          else
             return Num_Vecs.Next (Position);
          end if;
       end Next;
    end Splitting;



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30 19:30     ` Jeffrey Carter
  2012-05-30 20:54       ` Pascal Obry
@ 2012-05-31 14:09       ` Martin
  2012-05-31 20:58         ` tonyg
  1 sibling, 1 reply; 14+ messages in thread
From: Martin @ 2012-05-31 14:09 UTC (permalink / raw)


On Wednesday, May 30, 2012 8:30:21 PM UTC+1, Jeffrey Carter wrote:
> On 05/30/2012 01:10 AM, Martin wrote:
> >
> >        for Comment of Header_Comments loop
> >           Put_Line (File, Comment_Str&  Comment);
> >        end loop;
> >        if Include_Last_Saved_Time then
> >           Put_Line (File, Comment_Str&  "Last saved: "&  Image (Date =>  Clock));
> >        end if;
> >        for Section of This.Sections loop
> >           Put_Line (File, "["&  To_String (Section.Name)&  "]");
> >           for Pair of Section.Pairs loop
> >              Put_Line (File, To_String (Pair.Key)&  "="&  To_String (Pair.Value));
> >           end loop;
> >        end loop;
> 
> This uses 2 inline "for" loops, one containing a nested "for loop".
> 
> >        Close (File);
> >     exception
> >        -- implementation detail
> >     end Save;
> >
> > what we used to have (mocked up!):
> 
> This uses vector iterators.
> 
> While this is a nice feature, I don't think it's worth the added language 
> complexity.
> 
> In general, using "for" loops will be clearer than using iterators. In the case 
> of vectors (or unbounded arrays, to use their correct name), one can iterate 
> over them using "for" loops, and the use of iterators for an array abstraction 
> is a questionable practice:
> 
> for I in Header_Comments.First_Index .. Header_Comments.Last_Index loop
>     Put_Line (File, Comment_Str & Header_Comments.Element (I) );
> end loop;
> 
> if ... then
>     ...
> end if;
> 
> for I in This.Sections.First_Index .. This.Sections.Last_Index loop
>     Section := This.Sections.Element (I);
>     Put_Line ...
> 
>     for J in Section.Pairs.First_Index .. Section.Pairs.Last_Index loop
>        Pair := Section.Pairs.Element (J);
>        Put_Line ...
>     end loop;
> end loop;
> 
> I think this is equally clear and requires no additional language complexity.
> 
> Had your example used sets or maps it would have been a stronger argument.
> 
> -- 
> Jeff Carter
> "He didn't get that nose from playing ping-pong."
> Never Give a Sucker an Even Break
> 110
> 
> --- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net ---

Sorry, I just find that full of "noise" these days...to many characters that are just repeated. and 'Section' and 'Pairs' need to be declared somewhere too. I know you can get rid of the repetition with some 'renames' or a nested subprogram but that's just "noise" and makes more work for the reader.

Aside from the benefits Pascal mentions, the new syntax offers both readability *and writability* which is a bit of a departure for the language ;-)

-- Martin



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-31 14:09       ` Martin
@ 2012-05-31 20:58         ` tonyg
  0 siblings, 0 replies; 14+ messages in thread
From: tonyg @ 2012-05-31 20:58 UTC (permalink / raw)


On May 31, 2:09 pm, Martin <mar...@thedowies.com> wrote:
> On Wednesday, May 30, 2012 8:30:21 PM UTC+1, Jeffrey Carter wrote:
> > On 05/30/2012 01:10 AM, Martin wrote:
>
> > >        for Comment of Header_Comments loop
> > >           Put_Line (File, Comment_Str&  Comment);
> > >        end loop;
> > >        if Include_Last_Saved_Time then
> > >           Put_Line (File, Comment_Str&  "Last saved: "&  Image (Date =>  Clock));
> > >        end if;
> > >        for Section of This.Sections loop
> > >           Put_Line (File, "["&  To_String (Section.Name)&  "]");
> > >           for Pair of Section.Pairs loop
> > >              Put_Line (File, To_String (Pair.Key)&  "="&  To_String (Pair.Value));
> > >           end loop;
> > >        end loop;
>
> > This uses 2 inline "for" loops, one containing a nested "for loop".
>
> > >        Close (File);
> > >     exception
> > >        -- implementation detail
> > >     end Save;
>
> > > what we used to have (mocked up!):
>
> > This uses vector iterators.
>
> > While this is a nice feature, I don't think it's worth the added language
> > complexity.
>
> > In general, using "for" loops will be clearer than using iterators. In the case
> > of vectors (or unbounded arrays, to use their correct name), one can iterate
> > over them using "for" loops, and the use of iterators for an array abstraction
> > is a questionable practice:
>
> > for I in Header_Comments.First_Index .. Header_Comments.Last_Index loop
> >     Put_Line (File, Comment_Str & Header_Comments.Element (I) );
> > end loop;
>
> > if ... then
> >     ...
> > end if;
>
> > for I in This.Sections.First_Index .. This.Sections.Last_Index loop
> >     Section := This.Sections.Element (I);
> >     Put_Line ...
>
> >     for J in Section.Pairs.First_Index .. Section.Pairs.Last_Index loop
> >        Pair := Section.Pairs.Element (J);
> >        Put_Line ...
> >     end loop;
> > end loop;
>
> > I think this is equally clear and requires no additional language complexity.
>
> > Had your example used sets or maps it would have been a stronger argument.
>
> > --
> > Jeff Carter
> > "He didn't get that nose from playing ping-pong."
> > Never Give a Sucker an Even Break
> > 110
>
> > --- Posted via news://freenews.netfront.net/ - Complaints to n...@netfront.net ---
>
> Sorry, I just find that full of "noise" these days...to many characters that are just repeated. and 'Section' and 'Pairs' need to be declared somewhere too. I know you can get rid of the repetition with some 'renames' or a nested subprogram but that's just "noise" and makes more work for the reader.
>
> Aside from the benefits Pascal mentions, the new syntax offers both readability *and writability* which is a bit of a departure for the language ;-)
>
> -- Martin


very interesting. Thanks for the example and explaining it well
Martin. I really appreciate this because it does not come easily to
me, but once its there it sticks and is very useful. Is this going to
go into a wiki, maybe the danish ada mafia would host a gems like
section in there.



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-05-30 22:26     ` Georg Bauhaus
  2012-05-30 22:45       ` Georg Bauhaus
@ 2012-06-07  0:19       ` Randy Brukardt
  2012-06-07 12:42         ` Georg Bauhaus
  1 sibling, 1 reply; 14+ messages in thread
From: Randy Brukardt @ 2012-06-07  0:19 UTC (permalink / raw)


"Georg Bauhaus" <rm.dash-bauhaus@futureapps.de> wrote in message 
news:4fc69e72$0$6633$9b4e6d93@newsspool2.arcor-online.net...
...
> In Ada 2012, there is an Iterate function in the 2012 Vectors that
> takes a parameter Start : Cursor, but not a corresponding Finish : Cursor.

You don't really need one, because you can use "exit" in the for loop in 
order to stop the iteration early. And doing that explicitly does not suffer 
from the confusion that could occur if Finish is not actually after Start 
(in such a case, you'll probably iterate all the way to the end of the 
container; checking that Finish is somewhere after Start in the container is 
expensive in general so it isn't something that we wanted to do. So we left 
this operation out on purpose.

This does require using the cursor version of the iterator, so it is bit 
more wordy:

        for Cur in My_Vector.Iterate(Start) loop
             -- Operation code here, probably using My_Vector.Reference(Cur)
             --  to access and modify the element in place.
             exit when Cur = Finish;
       end loop;

The advantage here is that it is obvious what happens if Finish doesn't 
designate an element after Start in My_Vector: the iteration just goes to 
the end of My_Vector and stops.

> So I made a Forward_Iterator that would know Start and Finish.
> It has a construction function and overriding First and Next.
> This  made the whole program quite a bit longer.
> Not necessarily worse, I think, but longer.
> Perhaps more "rigorous", or "typish"?

Certainly possible, but not the recommended way to write such an iteration. 
Do you check for the error case of Finish not following Start in the 
container?

                                       Randy.





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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-06-07  0:19       ` Randy Brukardt
@ 2012-06-07 12:42         ` Georg Bauhaus
  2012-06-07 12:54           ` Georg Bauhaus
  0 siblings, 1 reply; 14+ messages in thread
From: Georg Bauhaus @ 2012-06-07 12:42 UTC (permalink / raw)


On 07.06.12 02:19, Randy Brukardt wrote:
> "Georg Bauhaus"<rm.dash-bauhaus@futureapps.de>  wrote in message
> news:4fc69e72$0$6633$9b4e6d93@newsspool2.arcor-online.net...
> ...
>> In Ada 2012, there is an Iterate function in the 2012 Vectors that
>> takes a parameter Start : Cursor, but not a corresponding Finish : Cursor.
>
> You don't really need one, because you can use "exit" in the for loop in
> order to stop the iteration early.

In the case of generic algorithms, the situation is a bit reversed,
since "it can stop the iteration early", where "it" is the generic
algorithm that has the for loop in its body. Using Ada 2005, the
generic algorithm need knowledge of a Cursor type and an Element
function:

       loop
          exit when Cur = One_After;
          Result := Binop (Result, Element (Cur));
          Cur := Next (Cur);
       end loop;

Using Ada 2012, the following looks nice, but might not (currently?)
be possible, because Cursor (detailed below) is an incomplete tagged
formal type of Iterator_Interfaces, and can't be used here:

       for Cur in Span loop     -- Span : Forward_Iterator'Class
	 exit when Cur = One_After;
          Result := Binop (Result, Element (Cur));
       end loop;

It also felt a little odd to have to pass both a Forward_Iterator
and a Cursor so that the loop could be stopped early. If the following
attempt is a possible solution at all.

The full algorithm below is adapted for use with Forward_Iterator
as you suggested (such as the one returned by function Vectors.Iterate)
IIUC. GNAT complains about invalid use and premature use of
Iteration.Cursor, more so in case I write "use type Iteration.Cursor".
(I have omitted testing for One_After "<=" Start.)

with Ada.Iterator_Interfaces;

generic
    type Element_Type is private;
    with package Iteration is new Ada.Iterator_Interfaces (<>);
    with function Element (Position : Iteration.Cursor) return Element_Type;
package Iterations_2012 is

    generic
       Zero      : in Element_Type;
       with function Binop (Left, Right : in Element_Type) return Element_Type;
    function Reduce_2012
      (Span	: in Iteration.Forward_Iterator'Class;
       One_After	: in Iteration.Cursor)  --!
    return Element_Type;
    --  Apply Binop to the sequence of elements in Span, excluding every
    --  element starting at One_After

end Iterations_2012;


package body Iterations_2012 is

    function Reduce_2012
      (Span	: Iteration.Forward_Iterator'Class;
       One_After	: Iteration.Cursor) return Element_Type
    is
       Result : Element_Type;
       use Iteration;  -- use type Iteration.Cursor; --!
    begin
       Result := Zero;
       for Cur in Span loop
	 exit when Cur = One_After;  --!
          Result := Binop (Result, Element (Cur));
       end loop;
       return Result;
    end Reduce_2012;

end Iterations_2012;


A typical scenario I have in mind is divide and conquer: there are tasks
that will perform some algorithm on (sub)sequences of elements from just
any container.



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

* Re: Ada2012 : In praise of 'for ... of ... loop'...
  2012-06-07 12:42         ` Georg Bauhaus
@ 2012-06-07 12:54           ` Georg Bauhaus
  0 siblings, 0 replies; 14+ messages in thread
From: Georg Bauhaus @ 2012-06-07 12:54 UTC (permalink / raw)


On 07.06.12 14:42, Georg Bauhaus wrote:

> Using Ada 2012, the following looks nice, but might not (currently?)
be possible, because Cursor (detailed below) is an incomplete <del>tagged</>
> formal type of Iterator_Interfaces, and can't be used here:



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

end of thread, other threads:[~2012-06-07 12:54 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-29 14:29 Ada2012 : In praise of 'for ... of ... loop' Martin
2012-05-29 15:02 ` Georg Bauhaus
2012-05-30  8:10   ` Martin
2012-05-30  8:15     ` Thomas Løcke
2012-05-30 16:21       ` Pascal Obry
2012-05-30 19:30     ` Jeffrey Carter
2012-05-30 20:54       ` Pascal Obry
2012-05-31 14:09       ` Martin
2012-05-31 20:58         ` tonyg
2012-05-30 22:26     ` Georg Bauhaus
2012-05-30 22:45       ` Georg Bauhaus
2012-06-07  0:19       ` Randy Brukardt
2012-06-07 12:42         ` Georg Bauhaus
2012-06-07 12:54           ` Georg Bauhaus

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