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-Thread: 103376,999932ecc319322a X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news4.google.com!newshub.sdsu.edu!npeer.de.kpn-eurorings.net!newsfeed.arcor.de!news.arcor.de!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: advice on package design Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.14.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <1110212638.336123.298580@l41g2000cwc.googlegroups.com> <1gbk0qx2sgzpg$.sltzfssofla8$.dlg@40tude.net> <3jok3ghqqls8$.1rrsonb8jsurt$.dlg@40tude.net> <88zllqj1min5$.fqqxis9i327d$.dlg@40tude.net> <18e9a92kz25wu$.8b965bel5vef$.dlg@40tude.net> <1dgodaruwhhwo$.1baazg490isjx.dlg@40tude.net> <1d0e316ux5h5u$.46x8kqxg4u3t$.dlg@40tude.net> Date: Mon, 21 Mar 2005 19:16:16 +0100 Message-ID: <1ffju2fe4dqmz$.10w4bxtx2kvs6$.dlg@40tude.net> NNTP-Posting-Date: 21 Mar 2005 19:16:17 MET NNTP-Posting-Host: 4f29a53c.newsread4.arcor-online.net X-Trace: DXC=7gCD3Q4Sb9I7ej[:C4ig8M:ejgIfPPldDjW\KbG]kaMHdbobRQ:W=WBjgejJV=G On 21 Mar 2005 11:17:28 -0500, Robert A Duff wrote: > "Dmitry A. Kazakov" writes: > >> On 17 Mar 2005 16:26:22 -0500, Robert A Duff wrote: >> >>> "Dmitry A. Kazakov" writes: >>> >>>> I like the separation very much. >>> >>> You're not alone. >>> >>> Part of my reason is that declarations in Ada execute code at run time. >>> In other languages (e.g. Pascal) there is a strict separation: >>> declarations declare, statements execute, so it makes sense to have >>> a syntactic line drawn between the two. But in Ada, the decls can >>> do real work, so the line drawn by the "begin" is misleading. >> >> Yes, indirectly they do. For the following body this is the code that never >> fail. Similarly, each "end;" is in fact also a code which again never fails >> (for the body above). I can buy this as modularization (can I sell it so >> too? (:-)) > > The problem is that whether something goes above or below the "begin" > depends on all kinds of extraneous factors. If I want to initialize a > variable with a function, it goes above the line. If I want to use > a procedure call, or a loop, it goes below the line. Etc. The effects of the declaration of an initialized variable and of a procedure call are fundamentally different. The first creates a new object for following scope. Evaluation of that object is rather a side effect. All things visible within the scope should be elaborated before "begin". What if I rename "declare" to "require", i.e. consider the declaration block as a precondition for following "begin". Will it look logical then? require X : T := ...; begin -- do something with X end; -- ensure that there is no X anymore The problem and difference with a procedure call is that it has no visible effect. If it had, then that could be put in the declaration block. >>> In some cases, the decls do *all* the work, especially when you're >>> working with Strings, where the length usually depends on the >>> initial value. Then the procedure body says "null;", meaning >>> "this does nothing", which is a lie. >> >> Yes. A similar case is: >> >> if 0 = Some_Win_API (...) then >> null; -- Don't care about your silly return codes! >> end if; > > It doesn't seem similar to me. Here, we are explicitly saying that the > "then" part does nothing, and that's a good thing. But the only effect of Some_Win_API is its side effect. Using if-then-else here is as misleading as null body of a procedure. It could even be written as such a procedure! procedure Some_Win_API_Wrapper (...) is Dummy : BOOL := Some_Win_API (...); begin null; end Some_Win_API_Wrapper; > (Some other > languages are more error prone in this regard.) But a procedure that > does a lot of work that happens to be above the "begin" still needs > "null", which seems sort of silly. I agree. But I think that the solution is a better balance between effects and side effects. I'd like to think of declarations as things done in parallel as opposed to serialized statements. Unfortunately this is also untrue in Ada. Serialization is extra coupling, I just feel that something must be wrong with that (like that "and" vs. "and then" debate, no good arguments for "and", but still...) >> I also dislike unnecessary indentations, but what if exception handling is >> needed? Then you have to create blocks anyway. > > I would prefer a separate try/catch-like statement for exception > handling. In C++ that only increases nesting as compared to Ada. > Exception handling seems totally unrelated to declaring > things, so I don't see why they should be mixed in the same syntax. It is rather mixed with scopes, which seems reasonable. Especially, if we consider exceptions as a part of the contract, which IMO is the only right way. >>... and also for forcing the compiler to >> evaluate statically known constraints at compile time and to remove them >> from all sorts of dopes. So instead of hiding the skeleton in the cupboard >> I would openly present it to the public! (:-)) > > I don't know how a language standard can *force* things like that. But it forces evaluation of static constants. We have to allow user-defined operations there. The type developer should be able to specify whether the discriminant (constraint) is embedded in each value or not. Then there should be a mechanism of constraint propagation like in: type (Size : Positive) is array (...) of Object (Size); >> I see. But that will require definition of which parts of which statements >> may act as scopes: loop, if alternative, case choice, exception choice >> (already so in the "X : others"-kludge), select choice etc. How many pages >> of ARM? (:-)) > > A small fraction of one page. ;-) > Any statement list should act as a scope. That will do the trick! (:-)) >>>> T := (1, 2, 4, declare X := 9, others => declare Y := 10); >>>> -- What would be this? How many Y's could be here? >>> >>> No, I don't propose to allow mixing of decls and expressions! >>> Just decls and statements. Decls don't return values. >> >> Once you let them in, then: if I can put declarations among statements, why >> cannot I put statements among declarations? > ^^^^^^^^^^^^ > You mean expressions? You can't put statements (or declarations) among > expressions because the type is wrong -- a statement does not return a > value of the right type (it doesn't return a value at all, or in C > terminology, it returns "void".) Parameterless functions do something out of nothing (:-)). But in the first place I meant declarations. Isn't it equivalent: if declarations and statements can be mixed then it is commutative and there is no more any distinction between them. So the following should be legal: package Funny is for I in 1..100 loop ... end loop; end Foo; package body Foo is X : Integer := 10; end Foo; BTW, it seems that there is a parallel to if-elsif-elsif-else. What about something in this spirit: declare ... begin then declare ... begin -- Better keywords needed then declare ... begin then declare ... begin end; It looks more structured than floating declarations. One could allow it in all lists of statements. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de