From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.5-pre1 Path: eternal-september.org!reader02.eternal-september.org!feeder.eternal-september.org!aioe.org!.POSTED.j1cmyFOIqnSpYf1NFre2bA.user.gioia.aioe.org!not-for-mail From: Blady Newsgroups: comp.lang.ada Subject: Re: Generalized Loop Iteration and User-Defined Indexing with more than two parameters. Date: Fri, 6 Nov 2020 16:39:09 +0100 Organization: Aioe.org NNTP Server Message-ID: References: <86361qwvht.fsf@stephe-leake.org> NNTP-Posting-Host: j1cmyFOIqnSpYf1NFre2bA.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:68.0) Gecko/20100101 Thunderbird/68.12.1 X-Notice: Filtered by postfilter v. 0.9.2 Content-Language: en-US Xref: reader02.eternal-september.org comp.lang.ada:60558 List-Id: Le 03/11/2020 à 12:05, Stephen Leake a écrit : > Blady 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.