comp.lang.ada
 help / color / mirror / Atom feed
From: Robert A Duff <bobduff@shell01.TheWorld.com>
Subject: Re: advice on package design
Date: 21 Mar 2005 15:35:36 -0500
Date: 2005-03-21T15:35:36-05:00	[thread overview]
Message-ID: <wccvf7k3ffr.fsf@shell01.TheWorld.com> (raw)
In-Reply-To: 1ffju2fe4dqmz$.10w4bxtx2kvs6$.dlg@40tude.net

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> 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".

Well, I've considered a language design in which initialization (or
should it be called "creation") is allowed to happen after the
declaration.  In this language, initialization has a different syntax
than assignment (":=" for init, ":==" for assignment, or some such).

So you could do:

    procedure P is
        X: T'Class; -- perhaps some syntax saying "do not default init".

        if ... then
            X := ...;
        else
            X := ...;
        end if;
        ...

You can do that in Ada, but you have to introduce pointers,
and you don't always want pointer semantics.

I would have compile-time rules that ensure an object is initialized
(created?) before being used or assigned; the compiler would have to do
a bit of flow analysis to check these rules.

If you do *that*, then an 'out' parameter can either assign into the
actual, or initialize the actual.  Programmer's choice.

>... 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

Sorry, I guess this is a matter of taste, and my taste says I don't like
the extra verbiage required just to declare X.

Note that I'm not against block statements.  I would allow:

    procedure P is
        begin
            X: ...;
            Y: ...;

            some statements
        end;
        begin
            -- X and Y not visible here.
            A: ...;
            B: ...;

            some statements
        end;
    end P;

or something like that.  But I wouldn't *require* the begin/end,
if you already have "then/end if" or something that delimits
the scope.

> 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!

Yes, I suppose you're right about that.  I suppose the best way to write
that would be:

    Ignore_Result(Some_Win_API(...));

where Ignore_Result is a predefined procedure that takes a parameter of
type Anything'Class.

> 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 agree, but I think the same is true of statements.  I've thought of
giving the programmer the choice: evaluate a sequence in parallel (and
the compiler checks that there are no bad interactions) or evaluate a
sequence in textual order.  Perhaps use "," to separate parallel things,
and ";" to separate sequential things.  So:

    X: Integer := 1,
    Y: Integer := 2;
    Z: Integer := X + Y;

meaning first create and initialize X and Y in parallel, and then create
and init Z.  I agree with your "extra coupling" point, but I think it
applies equally to decls and statements.  And I think the programmer
should have the choice of specifying sequential order (in both cases).

> >> 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.

That's OK -- the extra nesting implies some meaning.

> > 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.

I agree about the contract.  Java does this, but it gets some details
wrong.  I want a way to specify defaults.  For example, in a real-time
embedded program, I might want to explicitly mark every procedure that
can raise Storage_Error, but in a compiler, that's a waste, since
pretty-much anything can raise S_E.  Also, when passing procedures as
parameters, as in iterators, I want a way to say "this thing propagates
whatever the passed procedure propagates".

> >>... 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.

It pretends to.  I claim you can't write an ACATS test that determines
whether an Ada compiler evaluates static constants at compile time.

But that's OK -- compiler writers are sometimes stupid or lazy, but we
can trust them to not deliberately sabotage their products!

>...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);

Yes, I have similar notions about how compilers should deal with
discrims (stored with objects vs. not stored with objects).
Pragmas seem appropriate here, since it's purely an efficiency choice.
It's like pragma Inline -- sometimes you want it, sometimes you don't
(both for efficiency), but there's no ACATS test that can detect
whether the compiler is obeying your pragmas Inline.

Note that Ada 9X proposed to allow discriminated arrays,
but unfortunately that was rejected.

> >> 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
>    <statements>
> then declare ... begin -- Better keywords needed
>    <statements>
> then declare ... begin
>    <statements>
> then declare ... begin
>    <statements>
> end;
> 
> It looks more structured than floating declarations. One could allow it in
> all lists of statements.

How about if I just promise to leave a blank line between groups of
decls and groups of statements?  ;-)

    begin
        Obj1: ...;
        Obj2: ...;

        Grind_Upon(Obj1, Obj2);

        Obj3: ...;

        Obj3 := Obj1 + Obj2;
        Obj3 := Obj3 + 1;
    end;

> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

- Bob

P.S. I suppose the folks who want to talk about Ada on comp.lang.ada (as
opposed to some mythical language that is like Ada, only different) are
rather bored by this discussion.  But I think language design is fun!



  reply	other threads:[~2005-03-21 20:35 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-07 16:23 advice on package design spambox
2005-03-07 21:08 ` Dmitry A. Kazakov
2005-03-08 12:48   ` spambox
2005-03-08 17:18     ` Dmitry A. Kazakov
2005-03-12 19:57   ` Robert A Duff
2005-03-12 20:45     ` Dmitry A. Kazakov
2005-03-12 21:59       ` Robert A Duff
2005-03-13  9:23         ` Dmitry A. Kazakov
2005-03-16 20:41           ` Robert A Duff
2005-03-17 10:22             ` Dmitry A. Kazakov
2005-03-17 14:04               ` Robert A Duff
2005-03-17 15:59                 ` Dmitry A. Kazakov
2005-03-17 19:10                   ` Robert A Duff
2005-03-17 19:47                     ` Martin Dowie
2005-03-17 20:55                       ` Robert A Duff
2005-03-17 21:14                         ` Marius Amado Alves
2005-03-18  9:31                           ` Martin Dowie
2005-03-18  9:38                         ` Martin Dowie
2005-03-21 16:19                           ` Robert A Duff
2005-03-17 20:48                     ` Dmitry A. Kazakov
2005-03-17 21:26                       ` Robert A Duff
2005-03-18  3:06                         ` Jared
2005-03-18 10:00                         ` Dmitry A. Kazakov
2005-03-21 16:17                           ` Robert A Duff
2005-03-21 18:16                             ` Dmitry A. Kazakov
2005-03-21 20:35                               ` Robert A Duff [this message]
2005-03-22 10:55                                 ` Dmitry A. Kazakov
2005-03-17 23:23                 ` Randy Brukardt
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox