From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!nntp-feed.chiark.greenend.org.uk!ewrotcd!newsfeed.xs3.de!io.xs3.de!news.jacob-sparre.dk!franka.jacob-sparre.dk!pnx.dk!.POSTED.rrsoftware.com!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Why does Ada.Iterator_Interfaces specify Next as a function rather than a procedure? Date: Wed, 6 Sep 2017 16:50:47 -0500 Organization: JSA Research & Innovation Message-ID: References: <693d41af-1da7-4c47-825a-198a082aaf9a@googlegroups.com> Injection-Date: Wed, 6 Sep 2017 21:50:47 -0000 (UTC) Injection-Info: franka.jacob-sparre.dk; posting-host="rrsoftware.com:24.196.82.226"; logging-data="6503"; mail-complaints-to="news@jacob-sparre.dk" X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.7246 Xref: news.eternal-september.org comp.lang.ada:47957 Date: 2017-09-06T16:50:47-05:00 List-Id: (1) The ARG is looking at alternative kinds of iterators for Ada 2020. See AI12-0188-1 and AI12-0189-1 (probably only one of these will be used). (2) Ada 2012 changed the rules to reflect that the Rosen trick and its brother, the squirreling controlled type (used a lot by Claw) are legitimate techniques, even if they cause a constant to be modified. (Essentially, true constants are impossible for some kinds of types.) (3) So, making the iterator type use one of these techniques, or simply have it contain a pointer to a writable state object, should solve the problem. (But I agree it is not optimal, thus item (1)). That is, For Ada 2012 I'd define this something like: type State is record -- The components of the state. end record; type My_Iterator is new Ada.Finalization.Controlled and Reversible_Iterator with record My_State : access State; -- Writable state. The_State : aliased State; end record; procedure Initialize (Obj : in out My_Iterator) is begin Obj.My_State := The_State'Access; -- (*) end Initialize; (*) This might need to be Unchecked_Access. If so, it is safe, since the designated data will always live as long as the pointer -- they're both parts of the same object! Unless someone copies the pointer to a global variable -- but hopefully this is used in a private type so clients can't do that -- in that case, only you could do something stupid. ;-) Initialize will be called whenever any My_Iterator object is created, and the object is always a variable at that time. Thus, you can save a writable pointer at the time, and use it later even if you only have a constant view of the object. This is a legitimate technique -- it is NOT erroneous in Ada 2012 -- so if your compiler has problems with it, file a bug report and if they don't believe that, send me a proposed ACATS test! Randy. "Stephen Leake" wrote in message news:693d41af-1da7-4c47-825a-198a082aaf9a@googlegroups.com... I have a fairly complex collection of stuff that I want to define an iterator for, so all clients access the stuff in the same order. The stuff is token definitions for a lexer; keywords, punctuation, whitespace, identifiers, numbers. Initially, I defined my own Cursor type, that stores iterators to the various pieces, and manages the transitions between them. Thus the Cursor type has state, and the "Next" subprogram is a procedure. It is _not_ just "return node.next", but more like: if keywords not done, do Next (Keywords) elsif punctuation not done, do Next (Punctuation) with more logic that does First (Punctuation) at the right time. And so on for the rest of the stuff. Then I learned about Ada 2012 Iterators (allowing things like "for Token_Name of Tokens"), so naturally I tried to define one for this collection. It all goes well until I hit the definition of Ada.Iterator_Interfaces.Next; it must be a function, with an "in" parameter. I can work around this with an access type, but that's just annoying. And since I would be lying to the compiler, I'm not clear what subtle bugs I might encounter. For example, the compiler might assume that it can do: Next_Cursor := Next (Cursor); and Next_Cursor and Cursor have different values (ie refer to different items). I can't think of why it would want to do that for a loop, but since the current definition of Next allows it, I worry about it. If I don't use an access type, I'll have to copy the Cursor state in each call to Next, then modify it and return that. This is not in a time critical loop, so that's not really a problem, but it seems a silly waste. And my next use case could very well be in a time critical loop. The Annotated Ada Reference Manual doesn't shed any light on this. Would it be a problem to change Ada.Iterator_Interfaces.Next (and Previous) to take an "in out" parameter for the Cursor? Or provide an alternate procedure Next? I guess that would have to be in a different package. -- Stephe (I realize I'm over five years late with this, but better late than never :)