Ada '0x generics brain-fartz (long) 
Author Message
 Ada '0x generics brain-fartz (long)

There haven't been too many times when I've wanted Ada95 to do
something more or different than it already does.  The few times I
have, it usually turns out that someone else has already thought it
through long before and more thoroughly (like "limited access"... BTW I
still want it :-).  I've seen plenty of ideas for "improvements" to Ada
that are unnecessary and/or unworkable and/or bizarre.

So I humbly submit an idea... actually two ideas... for improvements to
Ada.  Although as essentially convenience features they border
on "unncessary", to my limited brain they seem like the might be
workable, and they don't seem "bizarre" -- that is, they seem like they
fall within the "spirit" of Ada rather than doing {*filter*} to it.

CAVEAT EMPTOR: This is totally half-baked cerebroflatulence.  It may be
crap!

OK, idea #1: "generic specialization".  The thought is that you could
have a construct that could bind some (but not necessarily all) actual
parameters to formals in the manner of an instantiation.  This
construct creates a new generic, which can then be instantiated in the
normal way (or, of course, further specialized).  The idea is somewhat
analogous to the constraining of a subtype.  As a generic, it could be
named in a formal_package_declaration.

In addition, the package form of this construct might be allowed to
have its own declarative region (and its own private part).  If that
part contained constructs that required completions, then a body would
be required.  The idea here is loosely analogous to a derived type
adding new (that is, non-inherited) primitives.

Finally: an instance of a generic package specialization (crappy term,
but I'm not worried about that now) would (potentially) match a
formal_package_actual_part as an instance of any generic (package or
package specialization) that it (directly or indirectly) specializes.
To extend the derivation analogy, a hierarchy of generic
specializations would constitute a "specialization class" -- the
closure over specialization, and the matching rules for generic formal
packages would be modified so as to be "class-wide" with respect to
this "specialization class".  (If this analogy helps you understand the
idea, great... if not, then just forget it :-)... the analogy was not
what gave me the idea).

I have in mind a syntax something like this:

    generic
        <generic_formal_part>
    new
        <generic_package_name> [<generic_actual_part>]
    package_specification;

The generic_actual_part has to be complete, just like in an
instantiation of the named generic package.  But since the formal
parameter declarations of this construct are visible here, they can be
named in the generic_actual_part -- this "passes through" parameters of
the specialization to the generic being specialized.  And of course, an
(explicit) actual parameter to the specialized generic can be an
expression that includes some of the formal parameters to the
specialization.

Example:

    -- A normal generic package...
    --
    generic
        with type T is private;
        Size : Positive;
        Frutzable : Boolean;
    package Base is
        Snarkify (This : in out T);
        Desnarkify (This : in out T);
    end Base;

    --
    -- A specialization!
    --

    type My_Type is <whatever...>  -- or, think "formal type of an
                                   -- enclosing generic"...

    generic
        Size : Positive;
        Frutzable : Boolean;
    new Base (My_Type, Size, Frutzable)
    package Special is
        Refloobimerize (This : in out My_Type);
    end Special;

    -- A further specialization
    --
    generic
        Exooberated : Boolean;
    new Special (
            Size => 20,    -- (named association this time)
            Frutzable => Exooberated and not Something_Else
        ) package More_Special
    is
    end More_Special;
.
.
.
        -- An instantiation
        --
        package P is new More_Special (Exooberated => False);
        X : My_Type;
    begin
        .
        .
        .
        P.Snarkify (X);        -- (from the "base" generic)
        P.Refloobimerize (X);  -- (from a specialization)
.
.
.
    --
    -- In a generic formal package
    --

    generic
       with package Template is new Base (<>);
    package Gee is
        <whatever...>
    end Gee;

    -- Instantiation of a specialization of Base (via Special),
    -- just like in the earlier example:
    --
    package Pee is new More_Special (Exooberated => False);

    package Gee_Pee is new Gee (Template => Pee);
    --
    -- ...So Gee_Pee gets a "view" of Pee as an instance of Base.
    --

Do you know why I came up with this idea?  Neither do I! :-)  Except
that I seem to remember thinking that it would save a lot of renames in
certain situations!  Get it?

Another application of this idea would be where you have a base generic
with a formal type that makes fewer assumptions (that is, creates a
_more_ restrictive view, e.g. limited, or with unknown discriminants,
or abstract tagged vs. not abstract) and then extend it by a
specialization, with a formal type that makes more assumptions (e.g.
tagged vs. ?, unlimited, etc.) and adds new operations that would be
have been illegal in the base generic due to the more restrictive view
of the type.  Now you have a generic that can be instantiated on some
types and provides the base functionality, and another generic that
would be instantiable for a subset of those types allowed for the base
generic, which would provide the base functionality plus extended
functionality that only makes sense for the types in the subset (you
instantiate the specialization, not the base and the specialization).
Make sense?  This application is really a special case of the "lots of
renames" scenario, because the way you do this in Ada95 is to use lots
of renames (and in Ada95, adding functionality to the "base" requires a
cascade of modifications to the extended/specialized forms to propagate
the new declarations).

Visibility of private parts would be like for child packages -- the
private part and body of a specialization can see the private parts of
whatever it's (transitively) specializing.  Not sure about bodies yet
(like I said... half-baked idea).

OK, here is the much shorter Idea Number Two: anonymous instantiation.
No windy discussion required here, you can figure it out from an
example:

    -- Normal Ada95...
    --
    generic
    package Gen is
        <whatever...>
    end Gen;

    -- Still normal...
    --
    generic
        package Template is new Gen (<>);
    package Eric is
        <whatever...>
    end Eric;

    -- An anonymous instantiation!
    --
    package Gen_Eric is
        new Eric (Template => new Gen (<whatever...>);

The purpose is to lower syntactic overhead and increase clarity, when
you're building chains of generic instantiations where the only purpose
of some instantiations is to serve as actuals to generic formal
packages (in particular with the "signature package" idiom, but by no
means just in that case).

OK, shoot me down in flames!  Who knows what hideous ramifications
lurk, what broken invariants?  I leave it to the language lawyers...

-- mark

Mark Lundquist
Rational Software

Sent via Deja.com
http://www.*-*-*.com/



Sun, 15 Jun 2003 16:10:24 GMT  
 Ada '0x generics brain-fartz (long)

Deja alert! :-)

For anyone reading my previous post from Deja.com, watch out -- deja
splits it into two "segments" (pages), and if you don't notice that you
have to click something to get the rest of it, you won't see the full
thing.  On my post, deja split it at a place where it almost looks like
it might have been the end of the message.

The slight reformatting of the source code examples is also courtesy of
deja :-/

-- mark

Mark Lundquist
Rational Software

Sent via Deja.com
http://www.deja.com/



Mon, 16 Jun 2003 01:48:26 GMT  
 Ada '0x generics brain-fartz (long)

When I first got this idea, I was thinking of it the way I described it
in my past -- as a new construct.  In the original post I called this
construct a "generic specialization".

But this morning I realized what it really is: a generalization of the
definition of a generic.  I became aware of this upon consideration of
the fact that there are no rules, beyond those for any ordinary
generic, governing the formal parameters for any
given "specialization".  The only rule pertains to the "new generic_
(package|procedure|function)_name" part, and that rule is that the
named generic be fully "provisioned" (that is, supplied with actuals,
like in an instantiation).  The effect of "partially binding" the
parameters of the base generic is simply a usage idiom, in which the
extending generic declares some formals which match some formals of the
base generic and then "passes them through".  But it need not pass
anything through, and in addition it may declare its own new formals
that have nothing to do with any formals of the base generic.
(Returning to the record extension analogy, the idea here is similar to
a type extension with discriminants).

Defining this idea in the language as "generics generalized" looks
pretty simple.  First we factor out part of the instantiation syntax as
its own construct:

    generic_provision ::=
        new <generic_name> [<generic_actual_part>];

The syntax for instantion gets rewritten as (e.g. for packages):

    generic_package_instantiation ::=
        <defining_program_unit_name> is <generic_package_provision>;

Now, the new, generalized syntax for a generic package becomes:

    generic_package_declaration ::=
        <generic_formal_part> [<generic_package_provision>]
package_specification;

(et cetera likewise for generic subprograms...)

All we did was add a new optional part.

A "baseless" generic (without the optional provision, that is, an Ada95-
compatible generic) can be thought of as implicitly an extension of an
anonymous, "null" base generic.  Not a particularly useful way of
thinking of it, except to emphasize that the new generic definition
really is the general case.  For instance,

    generic
        <whatever...>
    package Foo is
        <whatever...>
    end Foo;

is precisely equivalent to

    generic
    package Root_Of_All_Evil is
    end Root_Of_All_Evil;

    generic
        <whatever...>
    new Root_Of_All_Evil
    package Foo is
        <whatever...>
    end Foo;

A final note on the generalized generics idea... I see no reason for it
not to work seamlessly with generic child units.  A generic extending
another generic that is a child generic would have to be declared as a
child of the same parent as the generic being extended, e.g.:

    generic
    package Parent is
    end Parent;

    generic
    package Parent.Base_Child is
    end Parent.Base_Child;

    generic
    new Parent.Base_Child
    package Parent.Extended_Child is
    end Parent.Extended_Child;

    package P is new Parent;
    package BC is new P.Base_Child;
    pacakge EC is new P.Extended_Child;

The introduction of generic_provision also helps define the syntax for
my other idea, anonymous instantiation.  The <package_instance_name>
alternative for an <explicit_generic_actual_parameter> [RM12.3(5)]
would be replaced with <explicit_generic_actual_package>, defined as
follows:

    <explicit_generic_actual_package> ::=
        <package_instance_name> | <generic_package_provision>

all for now,
-- mark

Mark Lundquist
Rational Software

Sent via Deja.com
http://www.deja.com/



Mon, 16 Jun 2003 03:59:03 GMT  
 Ada '0x generics brain-fartz (long)

Quote:
> There haven't been too many times when I've wanted Ada95 to do
> something more or different than it already does.  

Ha! Dullard. ;-) (Really, no offense intended!)

Quote:
> So I humbly submit an idea... actually two ideas... for improvements to
> Ada.  Although as essentially convenience features they border
> on "unncessary", to my limited brain they seem like the might be
> workable, and they don't seem "bizarre" -- that is, they seem like they
> fall within the "spirit" of Ada rather than doing {*filter*} to it.

> CAVEAT EMPTOR: This is totally half-baked cerebroflatulence.  It may be
> crap!

I've had similar desires myself when recoding the C++ STL in Ada 95. Not
quite the same as yours though.

Quote:
> OK, idea #1: "generic specialization".  The thought is that you could
> have a construct that could bind some (but not necessarily all) actual
> parameters to formals in the manner of an instantiation.  This
> construct creates a new generic, which can then be instantiated in the
> normal way (or, of course, further specialized).

What I've usually pined for is the "dual" of that feature, a kind of
signature inheritance where I could extend a signature package with more
features by naming the parent signature and the new features. But I can
see why you'd want specialization too.

[...snip...]

Quote:
> OK, here is the much shorter Idea Number Two: anonymous instantiation.
> No windy discussion required here, you can figure it out from an
> example:

>     -- Normal Ada95...
>     --
>     generic
>     package Gen is
>         <whatever...>
>     end Gen;

>     -- Still normal...
>     --
>     generic
>         package Template is new Gen (<>);
>     package Eric is
>         <whatever...>
>     end Eric;

>     -- An anonymous instantiation!
>     --
>     package Gen_Eric is
>         new Eric (Template => new Gen (<whatever...>);

> The purpose is to lower syntactic overhead and increase clarity, when
> you're building chains of generic instantiations where the only purpose
> of some instantiations is to serve as actuals to generic formal
> packages (in particular with the "signature package" idiom, but by no
> means just in that case).

For this kind of thing I'd prefer automatic generic instantiation, similar
to what C++ does. There was an article about this in Tri-Ada 91 and a PhD
thesis from one of the authors (Shen) but no implementation I know
of. This would make Ada far more powerful, giving it a kind of parametric
polymorphism. Currently, generics do not give parametric polymorphism
but only a very crude approximation. I doubt we'll ever see this in any
version of Ada so if you really desire this you'll have to wait for
Generic Java or better yet use a modern statically typed functional
programming language like Ocaml, Haskell, Clean, or Mercury.

-- Brian



Fri, 20 Jun 2003 11:00:39 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. generics using generics (long)

2. Ada 0x Wish List

3. TestCase pattern brainstorming. Warning: Long brain dump

4. Platform dependant behaviour query (suspected Windows brain death) - long

5. ASIS problem with generics (Long)

6. Fwd: [LogoForum] Left Brain/Right Brain

7. Left Brain Right Brain

8. Fwd: [LogoForum] Left Brain/Right Brain

9. Left Brain Right Brain

10. LONG: Reliable Software Technologies (Ada-Europe'96)

11. TRI-Ada '92 Advance Program (VERY LONG)

12. Generics: 'Retraction' and an example

 

 
Powered by phpBB® Forum Software