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!mx02.eternal-september.org!feeder.eternal-september.org!news.glorb.com!peer01.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!post01.iad.highwinds-media.com!fx02.iad.POSTED!not-for-mail From: Brad Moore User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 Newsgroups: comp.lang.ada Subject: Re: A few questions References: In-Reply-To: Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Message-ID: NNTP-Posting-Host: 68.145.219.148 X-Complaints-To: internet.abuse@sjrb.ca X-Trace: 1423490207 68.145.219.148 (Mon, 09 Feb 2015 13:56:47 UTC) NNTP-Posting-Date: Mon, 09 Feb 2015 13:56:47 UTC Date: Mon, 09 Feb 2015 06:56:46 -0700 X-Received-Bytes: 6781 X-Received-Body-CRC: 4269868536 Xref: news.eternal-september.org comp.lang.ada:24926 Date: 2015-02-09T06:56:46-07:00 List-Id: On 15-02-08 03:37 PM, Laurent wrote: > On Saturday, February 7, 2015 at 11:14:46 PM UTC+1, Brad Moore wrote: > >> One way to get around this, is to define List_Ptr as a private type in >> the visible part of the package. >> >> eg. >> >> type List_Ptr is private; > > Ok that makes sense. As the package is based on an example from my Ada95 book, only the List type is visible. But the author had probably a good reason to design it like this? I believe you are referring to the example which appears on page 524 in John's 2005 book. I think it is generally desirable to not expose access types in the visible part of a package, and generally this should be possible. For a list package, exposing an Iterator or Cursor type is a cleaner approach, since you can hide any access values it may contain in the private part of the package. Users of the package have a nice Iterator abstraction without having to deal with access types and access values. In John's example, his Iterator type has an anonymous access discriminant pointing to a List object. This allows the user to declare Iterator objects and tie them to a List object. The discriminant is not mutable so once the Iterator is declared, it always points to that particular list object. I would probably go one step further and try to hide the discriminant and provide a function that accepts a List object as a parameter, and returns an Iterator object. This would be used to initialize a declaration of an iterator object. The Iterator could still have an anonymous access discriminant for a list in the private part, (or alternatively as a regular component of the Iterator object). If you want the Iterator to keep the discriminant, you can still hide it somewhat in the public part by declaring with unknown discriminants. i.e. type Iterator (<>) is limited private; This would also enforce that the only way to obtain an iterator would be through the function call. > >>> 65:20 (Ada 2005) cannot copy object of a limited type (RM-2005 6.5(5.5/2)) > > Oops wrong paragraphe, indeed meant 6.5(5.5/2) copied the wrong one > >> The compiler is complaining because you have declared It as a local >> object inside your Search function, and you are trying to return that >> object as the result of a function call, which involves copying the >> object to wherever the result of the function call is to be placed. >> >> Limited types are not copyable. Is there a reason why you declared your >> Iterator type to be a limited type, (ie. with the keyword limited)? > > No idea why it is limited. Took the example of the active iterator from John Barnes Ada 2005 book. > > But again I suppose that the author had a good reason to make the Iterator limited? He probably wanted to enforce that users of the package are not allowed to copy Iterator objects, or reinitialize them. A good design restriction as it might prevent users from using the abstraction is some ways that were not intended by the designer of the package. It's generally better to use limited types if you can live with the restrictions. In this case, the designer doesn't want the user to copy iterator objects, which seems like a reasonable restriction. If you want to avoid returning limited types from function calls, (and having to use extended return statements), you might want to consider passing the Iterator as an in out parameter to the call, as in John's example for his "Next" procedure. This avoids copying objects of limited type. > > Hm yes was peaking inside the double_linked_list provided with gnat, hoping to find something > similar to my construction. I think I saw an example of what you mean. To complicate for the > moment. Probably much easier to remove the limited. I'd suggest you keep the limited, but try the above >> eg. >> >> return Result (L) : Iterator do >> null; >> end return; > > Result(L): Iterator -- compiler not happy. > Result: Iterator(L) do -- works. Yes I realized that after I hit send. I figured you'd figure it out though, as you did. > > So I modified Iterator to private only and adapted the search function: > > function Search (L : access List; Element : Element_Type) return Iterator is > It : Iterator (L); > > begin > Start (It); > while not Done (It) loop > if Equals (It.This.Element, Element) then > return Result : Iterator (L) do > Result := It; > end return; Result.This := It.This; Instead of Result := It? If Iterator is no longer limited, then you could just use a simple return, i.e. return It; But keeping this as limited, I think it would be better as an in out parameter. Then the Search can be used on an Iterator object that already is declared. Returning as a function result means Search can only be used to initialize an Iterator object. > end if; > Next (It); > end loop; > return Result : Iterator (L) do > It.This:= null; > Result := It; > end return; > end Search; > > Is that correct or just garbage. At least it compiles but that doesn't mean anything. At first glance this looks OK, but I think you should consider rewriting as an in out parameter. I think you'll like the result better. > Compiler is quite picky: That's what's great about Ada. :-) > > It.This:= null; > Result := It; > > That compiles but Result := null; won't, expecting Iterator getting access? Result is a record type, not an access type, so setting it to null shouldn't be possible. Did you want Result.This := null; instead? Brad > > Thanks for your patience > > Laurent >