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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 109fba,f92fbb4a0420dd57 X-Google-Attributes: gid109fba,public X-Google-Thread: 103376,f92fbb4a0420dd57 X-Google-Attributes: gid103376,public From: eachus@spectre.mitre.org (Robert I. Eachus) Subject: Iterators (was Re: some questions re. Ada/GNAT from a C++/GCC user) Date: 1996/03/30 Message-ID: #1/1 X-Deja-AN: 144937450 references: organization: The Mitre Corp., Bedford, MA. newsgroups: comp.lang.ada,comp.lang.c++ Date: 1996-03-30T00:00:00+00:00 List-Id: In article bobduff@world.std.com (Robert A Duff) writes: > > Is there any way in Ada to iterate abstractly over the contents of a > > container,... > Several ways: > - Write a generic procedure Iterate, which takes a formal > procedure representing the body of the loop -- that is, > the formal procedure says what to do for each element. Funny you should mention it... Right now I have two projects where I am dealing with a large mass (1000s) of source files. I need to run some tools over the code. The choice was between Ada and a shell script...I chose Ada: generic with procedure To_Do(File: in String); procedure Iterate_Files(Pattern: in String := "*"; Directory: in String := ""); -- This generic iterates over all files in a directory matching Pattern and -- calls To_Do once for each such directory entry. If a file has several -- links in the directory To_Do will be called once for each. (The body for SunAda/VADS is tacked on at the end of this message. It isn't all that complex. If someone wants to rewrite for GNAT and post, feel free, but there may be a lot of GNAT versions needed, I don't know if it is possible to share code between different operating systems.) Two observations. First, the generic procedure approach is certainly right for this case. Second, the VADS run-time provided a call for freeing A_Strings, but not for find_files.find_file_rec, so I put in the call for the A_Strings case only. If I felt that there would be hundreds of calls with different patterns, I probably would have gone through the pain of "fixing" the find_files package by adding the missing functionality. But in my case, the one call to A_Strings.Free(Next) is enough garbage collection for all practical purposes...the call in the exception handler is for style more than anything else. And I know that this is something I have said before, but this particular example is a good one. The primary argument in favor of compilers which support general garbage collection is that the end user shouldn't have to worry about garbage collection. But in this example 1) the user of the package sees no garbage ever and 2) managing memory "right" was an extremely small effort when writing the generic. Even if all Ada compilers had generalized garbage collectors, the right choice here would be to build a procedure which predictably cleaned up after itself rather than warning the user that there would be lots of garbage generated which might affect global performance. Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ---------------------------------------------------------------------------- -- generic -- with procedure To_Do(File: in String); with A_Strings; with File_Names; procedure Iterate_Files(Pattern: in String := "*"; Directory: in String := "") is Pat: A_Strings.A_String; Handle: File_Names.Find_File_Info; Next: A_Strings.A_String; begin if Directory = "" then Pat := A_Strings.To_A(Pattern); else Pat := A_Strings.To_A(Directory & "/" & Pattern); end if; Handle := File_Names.Init_Find_File(Pat); loop Next := File_Names.Find_File(Handle); if Directory = "" and then Next.s(1..2) = "./" then To_Do(Next.s(3..Next.len)); else To_Do(Next.s); end if; A_Strings.Free(Next); end loop; exception when File_Names.No_More_Files => A_Strings.Free(Pat); end Iterate_Files; ----------------------------------------------------------------------------- -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is...