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=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC 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: rogoff@sccm.Stanford.EDU (Brian Rogoff) Subject: Re: some questions re. Ada/GNAT from a C++/GCC user Date: 1996/03/29 Message-ID: X-Deja-AN: 144941230 references: organization: /u/rogoff/.organization reply-to: rogoff@sccm.stanford.edu newsgroups: comp.lang.ada,comp.lang.c++ Date: 1996-03-29T00: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. - Write a procedure that takes an access-to-procedure as a parameter. In standard Ada, this only works if the procedure being passed in is non-nested, which makes this technique fairly useless. In GNAT, you can "cheat", by using 'Unrestricted_Access, but that's not standard Ada. - Write an Iterator class. Define any particular loop by deriving from that, and overriding the Do_One_Element method, or whatever. I think there's an example in the Rationale. - For each data structure, define Start, Done, Current_Element, and Get_Next operations. Or some variation on this. Jon Anthony, where are you? :-) (FYI, Jon has a very nice approach to simulating Sather iters in Ada 95. I'll leave it for him to post.) None of these is as pretty as the Sather solution, but they achieve the main goal, which is to have the module that defines the data structure define how to loop, and the clients define what they do at each iteration. The Sather iteration abstraction is great, and should be considered for inclusion in future variants of Ada. Maybe now that GNAT exists, someone will make an iter enhanced Ada like language (Sada? Sadie?). Macros can be used to achieve that, but in many cases, so can procedures, generics, Sather's iterators, etc. IMHO, the more restricted features are generally better than macros. Macros are more powerful, but also more difficult to understand. TeX is a language that uses macros for just about everything, and I find TeX code to be totally incomprehensible, despite the fact that I've read the TeX Book 4 times. I agree, although just about any feature can be used to create unreadable code. Even simple procedure abstraction (named procedures) could be used in an obfuscatory manner (call "read" "write", "plus" "minus", etc.), though macros give a lot of rope by which to hang yourself. There is supposedly some work by Cardelli somewhere on the web about a clean approach to macros (yes I know about Scheme; this is supposed to be different). OK, I found it (I love the Web :-), it is called "Extensible Syntax with Lexical Scoping" and is available at http://www.research.digital.com/SRC/personal/Luca_Cardelli/Papers.html No I haven't read it; a friend told me about it. Looks interesting... > Why doesn't Ada 95 allow declarations to be interspersed with ordinary > statements as C++ does? (Or does it? _Ada as a Second Language_ is a > big book!) It seems to me that the C++ approach is a small but > definite win. Does it interact very badly somehow with all those > guarantees on elaboration order? To intersperse declarations, you have to use a block_statement, like this: for I in Some_String'Range loop -- I wish I could easily use an iterator here ;-) declare X: constant Character := Some_String(I); begin ... end; end loop; To me, the "declare", "begin", and "end" are just useless verbosity. I prefer the C++ rule. Yes, this seems needlessly verbose. Any Ada guru have a good reason why it has to be this way? > Someone remarked -- in this newsgroup recently IIRC -- that macros > were explicitly disallowed in the design goals for Ada (Ada 83?), > since they make programs hard to understand. I don't remember the > exact wording, but as I remember the key reason was that you would > never know what was a macro and what wasn't without reading the entire > program hunting for macro definitions. (I searched for `macro' in the > Rationale without success, so I'm just going on speculation and dim > memory here.) It seems to me that that is a funny objection: most > macro processors these days don't require a characteristic pattern to > introduce macro expansions, but as far as I can tell there's no reason > that you couldn't restrict macro expansion to e.g. patterns preceded > by the keyword `macro'. I don't think this is the main reason people think macros are hard to understand. As you say, it would be easy to design the syntax so that a macro invokation looks different from anything else. Macros are generally hard to understand for other reasons, I think. Part of the problem is the low-level character-based nature of macros. But as you point out below, that's not true of all known macro facilities. Part of the problem is the lack of scoping rules -- if a macro expansion refers to a global variable X, it's referring to whatever X happens to be lying around at the point of the macro expansion. Contrast that with Ada's generics, where the names are bound at the site of the generic itself. Part of the problem is that you have to imagine what the macro expands to in order to understand what it does, and complex code trasformations are hard to imagine accurately. TeX macros have additional problems, like the fact that you can't tell at the call site how many arguments are being passed -- in fact, you can't in general tell until run time. The Cardelli paper addresses the scoping issue (damn, now I'll have to read it). Here is the abstract: Extensible Syntax with Lexical Scoping A frequent dilemma in programming languages design is the choice between a language with a rich set of notations and a small, simple core language. We address this dilemma by proposing extensible grammars, a syntax-definition formalism for incremental language extensions ans restrictions. The translation of program written in rich object languages into a small code language is defined via syntax-directed patterns. In contrast to macro-expansion and program-rewriting tools, our extensible grammars respect scoping rules. Therefore, we can introduce binding constructs while avoiding problems with unwanted name clashes. We develop extensible grammars and illustrate their use by extending the lambda calculus with let-bindings, conditionals, and constructs from database programming languages, such as SQL query expressions. We then give a formal description of the underlying rules for parsing, transformation, and substitution. Finally, we sketch how these rules are exploited in an implementation of ageneric, extensible parser package. - Bob P.S. I hope you enjoy Ada. Why not get a copy of GNAT, and try it out? Seconded! -- Brian