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