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=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,d58628d74c8614d4,start X-Google-Attributes: gid103376,public From: adam@irvine.com Subject: Re: Active Iteration (was: How to use abstract data types) Date: 1998/05/08 Message-ID: <6ivjdn$k0m$1@nnrp1.dejanews.com> X-Deja-AN: 351489432 X-Http-User-Agent: Mozilla/3.0 (X11; I; Linux 2.0.18 i586) Organization: Deja News - The Leader in Internet Discussion X-Article-Creation-Date: Fri May 08 18:37:43 1998 GMT Newsgroups: comp.lang.ada Date: 1998-05-08T00:00:00+00:00 List-Id: Matthew, thanks for all the information---this really does help me see what's going on. > Use static binding when you need static binding, and use dynamic binding > when you need dynamic binding. Don't think that importing a formal derived > type is somehow "superior" to the traditional way. It's its complement, > not replacement. FWIW, I believe I do need dynamic binding in the tool I'm working on. Of course, I'm not actually working on a program to list book titles, but I am working on a program that will have to deal with some radically different types of files, and the program will either use a command-line option or take a peek at a file's header to figure out what kind of file it's dealing with. Sorry that I didn't make that clear when I came up with my "Libraries" example; I didn't see at the time that it was necessary to mention this. So if, say, the program asks the user to select a type of library from a menu, and then contains code like if Menu_Option = 1 then declare Lib : aliased Libraries.Test.Library := Libraries.Test.The_Library; begin Let_The_User_Play_With_The_Library (Lib'access); end; elsif Menu_Option = 2 then declare Lib : aliased Libraries.Another_Test.Library := Libraries.Another_Test.The_Library; begin Let_The_User_Play_With_The_Library (Lib'access); end; elsif Menu_Option = 3 then declare Lib : aliased Libraries.Amazon_Dot_Com.Library := Libraries.Amazon_Dot_Com.The_Library; begin .... some stuff to set up an FTP connection .... Let_The_User_Play_With_The_Library (Lib'access); end; . . . where Let_The_User_Play_With_The_Library's parameter is "access Root_Library'class", and Let_The_User_Play_With_The_Library somewhere down the road calls List_Books, it doesn't seem to me that the generic version you used in your previous example: procedure Library_Package.Test.List_Books is new Library_Package.List.List_Books (Source_Library => Test_Library'Class, Source_Iterator => Test_Iterator); with Library_Package.Test.List_Books; use Library_Package.Test.List_Books; procedure Libtest2 is The_Lib : Library_Package.Test.Test_Library; begin List_Books (The_Lib, "m"); end Libtest2; will work. However, the example code you included in your more recent example should work fine in a case like this. Am I understanding what's going on correctly? > 4) Constructors are functions in Ada. That means to create a new iterator > object on the heap, you don't return it as a procedure out param. It > should be a function that returns the type, ie > > function New_Iterator > (Lib : access Root_Library) return Iterator_Access is abstract; > > function New_Iterator > (Lib : access Test_Library) return Iterator_Access; In my original post, my procedure declaration looked like this: procedure Scan_By_Title (Lib : in Library; Reg_Expression : in String; Scan : out Scan_Info; RE_Error : out Boolean) is abstract; where Scan_Info is the iterator. This can't be made into a function because it returns two things. But I think I see what happened here. I was assuming that the function (or procedure) that constructed the iterator was also the one that set it up for the specific purpose I needed it for. (Which might be right in some cases.) Your example, though, has one function to create the iterator, and a second procedure (Scan_For_Substring) to actually start the scan process. OK, that makes sense. Actually, that's the kind of thing I was looking for with my original post. I presume that New_Iterator could create the iterator with some sort of "Useless" flag so that if you tried Get_Book or Is_Done or Advance on the iterator without one of the other setup routines, the program would get upset. > This is an example of an indefinate type - Root_Iterator'Class (remember, > all classwide types are indefinate) - that is also limited. For an > indefinate type, I need to give it some initial value, so I need to invoke > a constructor to do that. But I can't for limited types. Major league > bummer. Last time I saw a problem similar to this, it was in a little book by Joseph Heller . . . > 8) Don't have a primitive operation of a tagged type return a > specific type, ie > > function The_Library return Root_Library is abstract; That was my mistake. I should have had it return Root_Library'Class. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/ Now offering spam-free web-based newsreading