* Generalized Loop Iteration and User-Defined Indexing with more than two parameters. @ 2020-11-01 18:41 Blady 2020-11-03 11:05 ` Stephen Leake 0 siblings, 1 reply; 7+ messages in thread From: Blady @ 2020-11-01 18:41 UTC (permalink / raw) Hello, Let's take the following container with constant indexing for iteration: 6. type UXString is tagged private with 7. Constant_Indexing => Get, 8. Iterable => (First => First, Next => Next, Has_Element => Has_Element, Element => Get); 9. function Make (Value : String) return UXString; 10. function Length (Self : UXString) return Natural; 11. function Get (Self : UXString; Index : Positive; Substitute : in Character) return Character; 12. function First (Self : UXString) return Positive is (1); 13. function Next (Self : UXString; Index : Positive) return Positive is (Index + 1); 14. function Has_Element (Self : UXString; Index : Positive) return Boolean is (Index <= Self.Length); The Get constant indexing function has more than two parameters. GNAT 2020 compilation is ok with the "for ... in ... loop" form: 47. for I in S1 loop 48. C := S3 (I, '@'); 49. Put_Line (Character'pos (C)'img); 50. end loop; but not with the "for ... of ... loop" form (S2 and S3 loops): 51. for CC of S2 loop 52. C := CC; 53. F := CC = 'h'; 54. Put_Line (Character'pos (C)'img & F'img); 55. end loop; test_uxstrings_4.adb:51:17: error: missing argument for parameter "Substitute" in call to "Get" declared at line 11 56. for CC of S3 ('@') loop 57. C := CC; 58. F := CC = 'h'; 59. Put_Line (Character'pos (C)'img & F'img); 60. end loop; test_uxstrings_4.adb:56:14: error: container cannot be indexed with "A Character Type" What is the correct usage? Thanks, Pascal. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-01 18:41 Generalized Loop Iteration and User-Defined Indexing with more than two parameters Blady @ 2020-11-03 11:05 ` Stephen Leake 2020-11-06 15:39 ` Blady 0 siblings, 1 reply; 7+ messages in thread From: Stephen Leake @ 2020-11-03 11:05 UTC (permalink / raw) Blady <p.p11@orange.fr> writes: > Hello, > > Let's take the following container with constant indexing for iteration: > > 6. type UXString is tagged private with > 7. Constant_Indexing => Get, > 8. Iterable => (First => First, Next => Next, > Has_Element => Has_Element, Element => Get); > 11. function Get (Self : UXString; Index : Positive; > Substitute : in Character) return Character; Hmm. Aspect "Iterable" is not defined by Ada. It is defined by GNAT. The gnat reference manual says: * The value of `Element' is a primitive operation of the container type that takes both a container and a cursor and yields an `Element_Type', which must be a type declared in the container package or visible from it. For example: function Get_Element (Cont : Container; Position : Cursor) return Element_Type; So it should have complained that your "Element => Get" is illegal. > What is the correct usage? An iterator 'Element' function can take only two parameters; the same is true for standard Ada generalized iterators. A Constant_Indexing function can take more than two parameters, but you can only use it by indexing a container object directly (see LRM 4.1.6), A : UXString; for Position in A.First .. A.Last loop Foo := A (Position, Substitute => 'C'); ... -- -- Stephe ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-03 11:05 ` Stephen Leake @ 2020-11-06 15:39 ` Blady 2020-11-07 0:58 ` Randy Brukardt 0 siblings, 1 reply; 7+ messages in thread From: Blady @ 2020-11-06 15:39 UTC (permalink / raw) Le 03/11/2020 à 12:05, Stephen Leake a écrit : > Blady <p.p11@orange.fr> writes: > >> Hello, >> >> Let's take the following container with constant indexing for iteration: >> >> 6. type UXString is tagged private with >> 7. Constant_Indexing => Get, >> 8. Iterable => (First => First, Next => Next, >> Has_Element => Has_Element, Element => Get); > >> 11. function Get (Self : UXString; Index : Positive; >> Substitute : in Character) return Character; > > Hmm. Aspect "Iterable" is not defined by Ada. It is defined by GNAT. The > gnat reference manual says: > > * The value of `Element' is a primitive operation of the container > type that takes both a container and a cursor and yields an > `Element_Type', which must be a type declared in the container > package or visible from it. For example: > > function Get_Element (Cont : Container; Position : Cursor) return Element_Type; > > So it should have complained that your "Element => Get" is illegal. > >> What is the correct usage? > > An iterator 'Element' function can take only two parameters; the same is > true for standard Ada generalized iterators. > > A Constant_Indexing function can take more than two parameters, but you > can only use it by indexing a container object directly (see LRM 4.1.6), > > A : UXString; > > for Position in A.First .. A.Last loop > > Foo := A (Position, Substitute => 'C'); > ... Hello, Thanks Stephen, I hadn't noticed that Iterate aspect was a GNAT specific aspect. I've borrowed it from GNATColl XString type. Thus, I turn my program in a more Ada way: type UXString is tagged private with Default_Iterator => Iterate, Iterator_Element => Character, Constant_Indexing => Get; type Cursor is private; function Get (Self : UXString; Position : Cursor) return Character; function Has_Element (Position : Cursor) return Boolean; package UXString_Iterators is new Ada.Iterator_Interfaces (Cursor, Has_Element); function Iterate (Self : UXString) return UXString_Iterators.Forward_Iterator'Class; ... for I in S1.Iterate loop C := S1 (I); F := S1 (I) = 'h'; Put_Line (Character'pos (C)'img & F'img); end loop; for CC of S2 loop C := CC; Put_Line (Character'pos (C)'img); end loop; Ada RM 5.5.1 "User-Defined Iterator Types" says: "The Constant_Indexing aspect (if any) of an iterable container type T shall denote exactly one function with the following properties: ... if there are more than two parameters, the additional parameters all have default expressions." So I defines: function Get (Self : UXString; Position : Cursor; Substitute : in Character := '&') return Character; and then: for I in S1.Iterate loop C := S1 (I, '@'); F := S1 (I) = 'h'; Put_Line (Character'pos (C)'img & F'img); end loop; for CC of S2 loop C := CC; Put_Line (Character'pos (C)'img); end loop; However, I have 3 questions about iteration: 1) When using Default_Iterator aspect, both Iterator_Element and Constant_Indexing have to be defined also. If I understand why Constant_Indexing at least has to be defined, what is the purpose of Iterator_Element? 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal parameter instead of an abstract function of Forward_Iterator interface? As: function Has_Element (Object : Forward_Iterator; Position : Cursor) return Boolean is abstract; The current way requires that Cursor type has the container reference embedded and cannot be a simple index type. 3) Couldn't be the additional parameters of the Constant_Indexing function without parameters defaults and a for ... of form as one of the followings? function Get (Self : UXString; Position : Cursor; Substitute : in Character) return Character; ... for CC of S2 ('@') loop C := CC; Put_Line (Character'pos (C)'img); end loop; or less preferable: for CC of S2 loop C := CC ('@'); Put_Line (Character'pos (C)'img); end loop; Thanks for your answers, Pascal. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-06 15:39 ` Blady @ 2020-11-07 0:58 ` Randy Brukardt 2020-11-07 17:46 ` Blady 2020-11-07 23:54 ` Stephen Leake 0 siblings, 2 replies; 7+ messages in thread From: Randy Brukardt @ 2020-11-07 0:58 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 3487 bytes --] "Blady" <p.p11@orange.fr> wrote in message news:ro3qms$1vdh$1@gioia.aioe.org... > Le 03/11/2020 à 12:05, Stephen Leake a écrit : ... > Ada RM 5.5.1 "User-Defined Iterator Types" says: > "The Constant_Indexing aspect (if any) of an iterable container type T > shall denote exactly one function with the following properties: > ... > if there are more than two parameters, the additional parameters all have > default expressions." > So I defines: > function Get (Self : UXString; Position : Cursor; Substitute : in > Character := '&') return Character; > and then: > for I in S1.Iterate loop > C := S1 (I, '@'); > F := S1 (I) = 'h'; > Put_Line (Character'pos (C)'img & F'img); > end loop; > for CC of S2 loop > C := CC; > Put_Line (Character'pos (C)'img); > end loop; > > However, I have 3 questions about iteration: > 1) When using Default_Iterator aspect, both Iterator_Element and > Constant_Indexing have to be defined also. > If I understand why Constant_Indexing at least has to be defined, what is > the purpose of Iterator_Element? Iterator functions work on cursors. The "of" form works on elements. In order to figure out what constant indexing function to use in the element iterator, we need to know both the parameter and result types. (Remember that there can be many overloaded indexing functions, you're not restricted to a single function [just a single name].) > 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal > parameter instead of an abstract function of Forward_Iterator interface? > As: > function Has_Element > (Object : Forward_Iterator; > Position : Cursor) return Boolean is abstract; > The current way requires that Cursor type has the container reference > embedded and cannot be a simple index type. I suppose other designs could have been chosen. The generic one was the original proposal; probably the person that designed it doesn't use interfaces very much. (I think that was me. ;-). If I recall correctly, the original interface design didn't work at all, and the generic was a fix. But I don't remember any of the details anymore (could look them up, but would need more motivation for that :-). > 3) Couldn't be the additional parameters of the Constant_Indexing function > without parameters defaults and a for ... of form as one of the > followings? > function Get (Self : UXString; Position : Cursor; Substitute : in > Character) return Character; > ... > for CC of S2 ('@') loop > C := CC; > Put_Line (Character'pos (C)'img); > end loop; > or less preferable: > for CC of S2 loop > C := CC ('@'); > Put_Line (Character'pos (C)'img); > end loop; I suppose, but that sort of thing would substantially complicate the mechanism, especially resolution. Personally, I think of the "of" form of iterators as a convinient shorthand to be used only in limited circumstances. The cursor form ("in"), the more traditional form, should be used when you have more complex needs. For instance, for the above: for CC in S2.Iterator loop C := S2(CC, '@'); Put_Line (Character'pos (C)'img); end loop; Trying to jam everything into the shorthand just complicates the implementation and makes it a lot harder for the reader. Randy. > Thanks for your answers, Pascal. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-07 0:58 ` Randy Brukardt @ 2020-11-07 17:46 ` Blady 2020-11-10 1:45 ` Randy Brukardt 2020-11-07 23:54 ` Stephen Leake 1 sibling, 1 reply; 7+ messages in thread From: Blady @ 2020-11-07 17:46 UTC (permalink / raw) Le 07/11/2020 à 01:58, Randy Brukardt a écrit : > "Blady" <p.p11@orange.fr> wrote in message >> Le 03/11/2020 à 12:05, Stephen Leake a écrit : > ... >> Ada RM 5.5.1 "User-Defined Iterator Types" says: >> "The Constant_Indexing aspect (if any) of an iterable container type T >> shall denote exactly one function with the following properties: >> ... >> if there are more than two parameters, the additional parameters all have >> default expressions." >> So I defines: >> function Get (Self : UXString; Position : Cursor; Substitute : in >> Character := '&') return Character; >> and then: >> for I in S1.Iterate loop >> C := S1 (I, '@'); >> F := S1 (I) = 'h'; >> Put_Line (Character'pos (C)'img & F'img); >> end loop; >> for CC of S2 loop >> C := CC; >> Put_Line (Character'pos (C)'img); >> end loop; >> >> However, I have 3 questions about iteration: >> 1) When using Default_Iterator aspect, both Iterator_Element and >> Constant_Indexing have to be defined also. >> If I understand why Constant_Indexing at least has to be defined, what is >> the purpose of Iterator_Element? > > Iterator functions work on cursors. The "of" form works on elements. In > order to figure out what constant indexing function to use in the element > iterator, we need to know both the parameter and result types. (Remember > that there can be many overloaded indexing functions, you're not restricted > to a single function [just a single name].) Thanks for clarification, I get it now. IMHO this clearly reduces the possibilities of the "for ... of ... loop" form to only one driven by Iterator_Element aspect. We might imagine iterate on a container on more than one its attributes. Let's iterate for instance on a collection of cars (Car_Coll) with different brands (Brand) and colors (Color): CC1, CC2 : Car_Coll; ... for B : Brand of CC1 loop -- iterate on the car brands present inside CC1 ... for C : Color of CC2 loop -- iterate on the car colors present inside CC2 ... if Iterator_Element is set to Color for example then the following code is equivalent to the previous one: for C of CC2 loop -- iterate on the car colors present inside CC2 ... If Iterator_Element is not set then the type in the loop must be provided. The indexing function would be then chosen either by Iterator_Element (by default) or overridden by the type given in the loop. Do this would help someone? Probably not a lot but I would give more symmetry between two for loop forms. > >> 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal >> parameter instead of an abstract function of Forward_Iterator interface? >> As: >> function Has_Element >> (Object : Forward_Iterator; >> Position : Cursor) return Boolean is abstract; >> The current way requires that Cursor type has the container reference >> embedded and cannot be a simple index type. > > I suppose other designs could have been chosen. The generic one was the > original proposal; probably the person that designed it doesn't use > interfaces very much. (I think that was me. ;-). If I recall correctly, the > original interface design didn't work at all, and the generic was a fix. But > I don't remember any of the details anymore (could look them up, but would > need more motivation for that :-). Does a message on Ada Comments could help ;-)? >> 3) Couldn't be the additional parameters of the Constant_Indexing function >> without parameters defaults and a for ... of form as one of the >> followings? >> function Get (Self : UXString; Position : Cursor; Substitute : in >> Character) return Character; >> ... >> for CC of S2 ('@') loop >> C := CC; >> Put_Line (Character'pos (C)'img); >> end loop; >> or less preferable: >> for CC of S2 loop >> C := CC ('@'); >> Put_Line (Character'pos (C)'img); >> end loop; > > I suppose, but that sort of thing would substantially complicate the > mechanism, especially resolution. > > Personally, I think of the "of" form of iterators as a convinient shorthand > to be used only in limited circumstances. The cursor form ("in"), the more > traditional form, should be used when you have more complex needs. For > instance, for the above: > > for CC in S2.Iterator loop > C := S2(CC, '@'); > Put_Line (Character'pos (C)'img); > end loop; > > Trying to jam everything into the shorthand just complicates the > implementation and makes it a lot harder for the reader. This is connected to point 1): Do this would help someone? Probably not a lot but I would give more symmetry between two for loop forms. > Randy Thanks Randy for your answers, Pascal. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-07 17:46 ` Blady @ 2020-11-10 1:45 ` Randy Brukardt 0 siblings, 0 replies; 7+ messages in thread From: Randy Brukardt @ 2020-11-10 1:45 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1018 bytes --] "Blady" <p.p11@orange.fr> wrote in message news:ro6mhg$1lmd$1@gioia.aioe.org... > Le 07/11/2020 à 01:58, Randy Brukardt a écrit : ... >> I suppose other designs could have been chosen. The generic one was the >> original proposal; probably the person that designed it doesn't use >> interfaces very much. (I think that was me. ;-). If I recall correctly, >> the >> original interface design didn't work at all, and the generic was a fix. >> But >> I don't remember any of the details anymore (could look them up, but >> would >> need more motivation for that :-). > > Does a message on Ada Comments could help ;-)? I rather doubt a new design would be introduced, simply because it would be very complex to have multiple approaches working at the same time, and the problems with the existing design aren't as significant as many other things that could be fixed with Ada. (There's always a limited amount of effort that can be expended.) Randy. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. 2020-11-07 0:58 ` Randy Brukardt 2020-11-07 17:46 ` Blady @ 2020-11-07 23:54 ` Stephen Leake 1 sibling, 0 replies; 7+ messages in thread From: Stephen Leake @ 2020-11-07 23:54 UTC (permalink / raw) "Randy Brukardt" <randy@rrsoftware.com> writes: > "Blady" <p.p11@orange.fr> wrote in message > news:ro3qms$1vdh$1@gioia.aioe.org... > >> 2) In Ada.Iterator_Interfaces, why Has_Element is a generic formal >> parameter instead of an abstract function of Forward_Iterator interface? >> As: >> function Has_Element >> (Object : Forward_Iterator; >> Position : Cursor) return Boolean is abstract; >> The current way requires that Cursor type has the container reference >> embedded and cannot be a simple index type. > > I suppose other designs could have been chosen. In addition, you can store the container reference in your Iterator object. -- -- Stephe Written from unceded ancestral homelands of the Huichiun, an Ohlone people,for which I pay Shuumi Land Tax ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-11-10 1:45 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-11-01 18:41 Generalized Loop Iteration and User-Defined Indexing with more than two parameters Blady 2020-11-03 11:05 ` Stephen Leake 2020-11-06 15:39 ` Blady 2020-11-07 0:58 ` Randy Brukardt 2020-11-07 17:46 ` Blady 2020-11-10 1:45 ` Randy Brukardt 2020-11-07 23:54 ` Stephen Leake
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox