comp.lang.ada
 help / color / mirror / Atom feed
* User-defined type attributes
@ 2008-03-12 18:58 Eric Hughes
  2008-03-12 21:23 ` Dmitry A. Kazakov
  2008-03-14  1:46 ` Randy Brukardt
  0 siblings, 2 replies; 29+ messages in thread
From: Eric Hughes @ 2008-03-12 18:58 UTC (permalink / raw)


In light of the recent discussion of formal package parameters, I have
been wondering about user-defined type attributes.  They don't
currently exist in any version of Ada.

First, a historical question: Was there a proposal for user attributes
that was considered for Ada 2005?

My interest in them is akin to my interest in formal package
parameters.  The prefixed views for functions and procedures (dot-
notation) of Ada 2005 are directly analogous to what would be required
for attribute syntax.  This notation hints at the possibility of a
kind of visibility related to formal type parameters, one which would
make ordinary subprograms and attribute functions visible without
making the entire definition package visible.  The idea is that a
formal type parameter create a visibility related only to that type
itself.  In order to make this really useful, attribute functions
would be needed to forestall the use of an entire package, rather than
only a single type.

If this seems abstruse, just consider the character traits that the C+
+ standard library uses.

And a related historical question: Why does the prefixed view of a
subprogram only apply to tagged types?  It seems like a syntax
eminently suited for any subprogram.

An attribute function must evaluate at compile-time, or perhaps more
subtly, prior to elaboration time.  Much of the requisite apparatus is
already present with static expressions and preelaborable packages.
The standard would require an additional definition of the ability to
pre-elaborate a function body.  While such a body might be restricted
to returning a single static expression, that seem a bit restrictive.

My overall motivation (as before) is to enable better, more flexible
library support.  Library support gates usability and enables cost-
justifiable selection of Ada in a greater number of application
domains.  These kinds of features are not so critical for a single
team writing their own software, but rather come into their own when
writing libraries for other people to use in not-yet-anticipated ways.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-12 18:58 User-defined type attributes Eric Hughes
@ 2008-03-12 21:23 ` Dmitry A. Kazakov
  2008-03-13 18:32   ` Eric Hughes
  2008-03-14  1:46 ` Randy Brukardt
  1 sibling, 1 reply; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-12 21:23 UTC (permalink / raw)


On Wed, 12 Mar 2008 11:58:29 -0700 (PDT), Eric Hughes wrote:

> An attribute function must evaluate at compile-time, or perhaps more
> subtly, prior to elaboration time.  Much of the requisite apparatus is
> already present with static expressions and preelaborable packages.
> The standard would require an additional definition of the ability to
> pre-elaborate a function body.  While such a body might be restricted
> to returning a single static expression, that seem a bit restrictive.

Attributes in Ada aren't necessarily static, even type's attributes aren't.
To me static functions is an independent, yet important issue.

In my view attributes should be primitive operations. I would handle them
similarly to prefix notation. I.e. X(Y,Z), Y.X(Z), Y'X(Z) considered
equivalent. When applied to types, that should be treated just as a
parameter of the type Tag.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-12 21:23 ` Dmitry A. Kazakov
@ 2008-03-13 18:32   ` Eric Hughes
  2008-03-13 19:58     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Hughes @ 2008-03-13 18:32 UTC (permalink / raw)


On Mar 12, 3:23 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> Attributes in Ada aren't necessarily static, even type's attributes aren't.
> To me static functions is an independent, yet important issue.

Most attributes are completely static.  The ones that aren't (like
T'Callable, E'Caller) seem all to be of a kind that (1) statically
return a function (2) whose first parameter is the type of the object,
and then (3) apply it to that object.  Given that this is at least in
the spirit of a preelaborable attribute, there's the possibility of
treating these cases as syntactic shorthand: Obj'Attr for
Obj'Attr( Obj ), or alternately for Obj.Obj'Attr.  I did a brief scan
of ARM05/Annex-K just now, and this applies to all the cases I found
(which were all tasking or type attributes).

So I'll modify my idea to deal with historical syntax:
1) The definition of an attribute function has a static expression.
2) The syntax for invoking an attribute may imply a dynamic function
call.

Such implicit calls generate a syntax ambiguity between "attribute
procedure Op( X : T )" and "attribute procedure Op( X : T ; Y : T )"
when invoking with only positional parameters.  What would
Obj'Op( Obj ) mean?  I assume this can be adequately addressed.

> In my view attributes should be primitive operations. I would handle them
> similarly to prefix notation. I.e. X(Y,Z), Y.X(Z), Y'X(Z) considered
> equivalent.

The whole point of user attributes is to gain cleaner syntax for
referring to the environment of a type or object, that which is
available at pre-elaboration time, and supports generic programming
better.  Without such a syntax there are lots more formal parameters
that need to be forwarded around.

Just making attributes run-time functions eliminates a useful
distinction.  Functions on a type are part of the tradition algebraic
specification of a type.  Attributes on a type are part of the
language environment inside of which a type specification is
expressed.  These are very different.

> When applied to types, that should be treated just as a
> parameter of the type Tag.

That seems like the right way to treat the first parameter of an
implicit function call for an attribute on a type.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-13 18:32   ` Eric Hughes
@ 2008-03-13 19:58     ` Dmitry A. Kazakov
  2008-03-14  1:46       ` Randy Brukardt
                         ` (3 more replies)
  0 siblings, 4 replies; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-13 19:58 UTC (permalink / raw)


On Thu, 13 Mar 2008 11:32:23 -0700 (PDT), Eric Hughes wrote:

> On Mar 12, 3:23 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> Attributes in Ada aren't necessarily static, even type's attributes aren't.
>> To me static functions is an independent, yet important issue.
> 
> Most attributes are completely static.  The ones that aren't (like
> T'Callable, E'Caller) seem all to be of a kind that (1) statically
> return a function (2) whose first parameter is the type of the object,
> and then (3) apply it to that object.

In which sense function is static? If understand what you wrote, it simply
means that the name "Callable" is static. Yes it is.

> Given that this is at least in
> the spirit of a preelaborable attribute, there's the possibility of
> treating these cases as syntactic shorthand: Obj'Attr for
> Obj'Attr( Obj ), or alternately for Obj.Obj'Attr.

Yes, as well as, Attr (Obj), which would be IMO a better way. I think
everybody is tired writing Integer'Image(X) rather than X'Image.

>  I did a brief scan
> of ARM05/Annex-K just now, and this applies to all the cases I found
> (which were all tasking or type attributes).

Nevertheless the result is not static, thus it cannot be used, say, in a
declaration of a modular type. I consider this issue as fully independent.
We need static functions beyond attributes. Consider pattern matching:

   loop
      if Match (Text, Pattern ("*.ada")) then

there is no way to define Pattern in a way that would force the compiler to
translate "*.ada" at compile time.

> So I'll modify my idea to deal with historical syntax:
> 1) The definition of an attribute function has a static expression.
> 2) The syntax for invoking an attribute may imply a dynamic function
> call.
> 
> Such implicit calls generate a syntax ambiguity between "attribute
> procedure Op( X : T )" and "attribute procedure Op( X : T ; Y : T )"
> when invoking with only positional parameters.  What would
> Obj'Op( Obj ) mean?  I assume this can be adequately addressed.
> 
>> In my view attributes should be primitive operations. I would handle them
>> similarly to prefix notation. I.e. X(Y,Z), Y.X(Z), Y'X(Z) considered
>> equivalent.
> 
> The whole point of user attributes is to gain cleaner syntax for
> referring to the environment of a type or object, that which is
> available at pre-elaboration time, and supports generic programming
> better.  Without such a syntax there are lots more formal parameters
> that need to be forwarded around.

Why? The only thing you need is formal generic ADTs. Ada's generics lack
ADTs, which is the reason why you need to pass operations together with the
formal types. There exist formal built-in types like "private", "<>",
"digits <>" etc, but there is no user-defined ones. Add these and all
primitive operations will go with the actual type just per magic. It would
be IMO a natural step for anybody who wanted generics to evolve in an
Ada-way. (Not for me, as you know, I prefer generics removed from the
language.)

> Just making attributes run-time functions eliminates a useful
> distinction.  Functions on a type are part of the tradition algebraic
> specification of a type.  Attributes on a type are part of the
> language environment inside of which a type specification is
> expressed.  These are very different.

I don't see why this distinction is important. Anyway it leaks, because you
certainly need constrained types in the types algebra. This brings
discriminants with it. Do you want to introduce attributes for the
discriminants of a subtype? Like X'Tag? which is of course merely a
discriminant. I think it would be an overkill.

Then what would you do with 'Pos, 'Succ, 'Adjacent etc attributes which
have nothing to do with types algebra? In my view this distinction just
does not hold since Ada 95, because that introduced user-defined classes.
In my view attributes in Ada 83 meant mere "magical things",
meta-subprograms which profiles cannot be spelt in the language. This has
changed, we can spell most of them now as proper primitive subprograms.
More elaborated class model of Ada will become less "magical things" will
remain.

I think now X'Y notation should be considered as pure syntax sugar, with no
semantics.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-12 18:58 User-defined type attributes Eric Hughes
  2008-03-12 21:23 ` Dmitry A. Kazakov
@ 2008-03-14  1:46 ` Randy Brukardt
  2008-03-14  4:41   ` Eric Hughes
  1 sibling, 1 reply; 29+ messages in thread
From: Randy Brukardt @ 2008-03-14  1:46 UTC (permalink / raw)


"Eric Hughes" <eric.eh9@gmail.com> wrote in message
news:d9065e94-8586-4889-b5c7-a8ca9e8f2248@d21g2000prf.googlegroups.com...
...
> First, a historical question: Was there a proposal for user attributes
> that was considered for Ada 2005?

Not seriously. It had been rejected for Ada 95, and in general, we didn't
want to rehash that old ground.

...
> And a related historical question: Why does the prefixed view of a
> subprogram only apply to tagged types?  It seems like a syntax
> eminently suited for any subprogram.

There are ambiguity problems because "any type" includes access types.
Recall that '.' in Ada always includes an implicit dereference (and the
prefixed notation also supports the reverse, an implicit 'Access). That is,
   A.B(C);
could mean
   B(A, C);
or
   B(A.all, C);
or
   B(A'access, C);

The latter should not be allowed for untagged types (they're not implicitly
aliased). But, also it would be possible for it to mean
  B(A.all.all, C);
and
  B(A.all.all.all, C);
and so on forever.

That caused definitional and implementation problems. So we only allowed
tagged types.

That's OK, because only tagged types work "right" in Ada. There are a number
of bizarre behaviors (one involves "=" of types with components, and another
with the "reemergence" of predefined operations inside of a generic) that
had to be retained from Ada 83 for compatibility reasons. These language
mistakes are corrected with tagged types.

Thus, I think virtually all new composite types should be tagged in Ada
programs; you'll be a lot happier for it. Keep in mind that the only runtime
overhead for a tagged object in Ada is the space for the tag and the time to
fill it in on initialization; calls are statically bound unless you use
T'Class somewhere.

I usually go further and say all new types should be controlled (so as to
get user-defined finalization), but that does have a small runtime overhead
if not used.

                               Randy.






> An attribute function must evaluate at compile-time, or perhaps more
> subtly, prior to elaboration time.  Much of the requisite apparatus is
> already present with static expressions and preelaborable packages.
> The standard would require an additional definition of the ability to
> pre-elaborate a function body.  While such a body might be restricted
> to returning a single static expression, that seem a bit restrictive.
>
> My overall motivation (as before) is to enable better, more flexible
> library support.  Library support gates usability and enables cost-
> justifiable selection of Ada in a greater number of application
> domains.  These kinds of features are not so critical for a single
> team writing their own software, but rather come into their own when
> writing libraries for other people to use in not-yet-anticipated ways.
>
> Eric





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-13 19:58     ` Dmitry A. Kazakov
  2008-03-14  1:46       ` Randy Brukardt
  2008-03-14  1:46       ` Randy Brukardt
@ 2008-03-14  1:46       ` Randy Brukardt
  2008-03-14  3:55       ` Eric Hughes
  3 siblings, 0 replies; 29+ messages in thread
From: Randy Brukardt @ 2008-03-14  1:46 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:965suhjl0bxt$.74se2ylyksin.dlg@40tude.net...
...
> Why? The only thing you need is formal generic ADTs. Ada's generics lack
> ADTs, which is the reason why you need to pass operations together with
the
> formal types. There exist formal built-in types like "private", "<>",
> "digits <>" etc, but there is no user-defined ones. Add these and all
> primitive operations will go with the actual type just per magic. It would
> be IMO a natural step for anybody who wanted generics to evolve in an
> Ada-way. (Not for me, as you know, I prefer generics removed from the
> language.)

Generic formal derived types are the way to bring an ADT into a generic.
After all, they do bring in all of the primitive operations of the ADT.

The only problem is that they can't be used on unrelated types, but that's
not very relevant if you are using tagged types (and you might as well being
doing so if you're defining any sort of composite type).

                                                        Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-13 19:58     ` Dmitry A. Kazakov
@ 2008-03-14  1:46       ` Randy Brukardt
  2008-03-14  1:46       ` Randy Brukardt
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 29+ messages in thread
From: Randy Brukardt @ 2008-03-14  1:46 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:965suhjl0bxt$.74se2ylyksin.dlg@40tude.net...
...
> Why? The only thing you need is formal generic ADTs. Ada's generics lack
> ADTs, which is the reason why you need to pass operations together with
the
> formal types. There exist formal built-in types like "private", "<>",
> "digits <>" etc, but there is no user-defined ones. Add these and all
> primitive operations will go with the actual type just per magic. It would
> be IMO a natural step for anybody who wanted generics to evolve in an
> Ada-way. (Not for me, as you know, I prefer generics removed from the
> language.)

Generic formal derived types are the way to bring an ADT into a generic.
After all, they do bring in all of the primitive operations of the ADT.

The only problem is that they can't be used on unrelated types, but that's
not very relevant if you are using tagged types (and you might as well being
doing so if you're defining any sort of composite type).

                                                        Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-13 19:58     ` Dmitry A. Kazakov
  2008-03-14  1:46       ` Randy Brukardt
@ 2008-03-14  1:46       ` Randy Brukardt
  2008-03-14  9:00         ` Dmitry A. Kazakov
  2008-03-14 14:31         ` User-defined type attributes (replacing genericity) Georg Bauhaus
  2008-03-14  1:46       ` User-defined type attributes Randy Brukardt
  2008-03-14  3:55       ` Eric Hughes
  3 siblings, 2 replies; 29+ messages in thread
From: Randy Brukardt @ 2008-03-14  1:46 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:965suhjl0bxt$.74se2ylyksin.dlg@40tude.net...
...
> Why? The only thing you need is formal generic ADTs. Ada's generics lack
> ADTs, which is the reason why you need to pass operations together with
the
> formal types. There exist formal built-in types like "private", "<>",
> "digits <>" etc, but there is no user-defined ones. Add these and all
> primitive operations will go with the actual type just per magic. It would
> be IMO a natural step for anybody who wanted generics to evolve in an
> Ada-way. (Not for me, as you know, I prefer generics removed from the
> language.)

Generic formal derived types are the way to bring an ADT into a generic.
After all, they do bring in all of the primitive operations of the ADT.

The only problem is that they can't be used on unrelated types, but that's
not very relevant if you are using tagged types (and you might as well being
doing so if you're defining any sort of composite type).

                                                        Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-13 19:58     ` Dmitry A. Kazakov
                         ` (2 preceding siblings ...)
  2008-03-14  1:46       ` User-defined type attributes Randy Brukardt
@ 2008-03-14  3:55       ` Eric Hughes
  2008-03-14  9:01         ` Dmitry A. Kazakov
  3 siblings, 1 reply; 29+ messages in thread
From: Eric Hughes @ 2008-03-14  3:55 UTC (permalink / raw)


On Mar 13, 1:58 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> In which sense function is static? If understand what you wrote, it simply
> means that the name "Callable" is static.

That's not what I meant.  Here's some sample notation, whose syntax is
merely illustrative.

    -- Declaration of an attribute
    generic
        task type T ;
    function T'Callable return boolean ;

    -- Declaration of a (static) implementation function
    generic
        task type T ;
    function Callable_Impl return access function( X : T ) return
boolean is static ;

    -- Binding of an implementation to an attribute
    generic
        task type T ;
        Obj : T ;
    for Obj'Callable use Callable_Impl.all( X => Obj ) ;

Regardless of whatever syntax is appropriate, one of the things that
makes me uncomfortable about attributes is that their definitions
don't have the same rigor of notation in their definitions as, say,
the standard libraries do.  In the spirit of separation compilation,
I'd like to see attribute definitions in specification packages, even
if their bodies exist solely within a compiler's implementation.


I wrote:
> Functions on a type are part of the tradition algebraic
> specification of a type.  Attributes on a type are part of the
> language environment inside of which a type specification is
> expressed.  These are very different.

"Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote:
> I don't see why this distinction is important.

I'm afraid I don't know how to argue this point briefly.  It's the
difference between language (in the proof theory sense) and
metalanguage.  I guess I've done too much formal logic too see this
distinction and its import as anything other than obvious.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  1:46 ` Randy Brukardt
@ 2008-03-14  4:41   ` Eric Hughes
  2008-03-15  3:20     ` Randy Brukardt
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Hughes @ 2008-03-14  4:41 UTC (permalink / raw)


On Mar 13, 7:46 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
[re: consideration of user attributes]
> Not seriously. It had been rejected for Ada 95, and in general, we didn't
> want to rehash that old ground.

Hmm.  I do admit, unless you're specifically support heavy generic
programming, it's not all that useful.

I wrote:
> > And a related historical question: Why does the prefixed view of a
> > subprogram only apply to tagged types?  It seems like a syntax
> > eminently suited for any subprogram.

> There are ambiguity problems because "any type" includes access types. [...]
> That caused definitional and implementation problems. So we only allowed
> tagged types.

OK.  That's a can of worms.  I'm writing here, though, not to solve
that problem but to provide motivation about why a solution is
important.

> That's OK, because only tagged types work "right" in Ada. [...]
>
> Thus, I think virtually all new composite types should be tagged in Ada
> programs [...]

I'm with you on the general idea.  In my own code, most of my types
are tagged.  But the requirement to have them tagged in order to use
the "." operator forces a trade-off: either (a) restrict generic
parameters to tagged types or (b) avoid "." notation and be required
to pull in whole packages rather than only single types.  This doesn't
match up with the separation of concerns (a.k.a. orthogonality) which
is one of the hallmarks of Ada and one of the things I appreciate most
about the language.  The power of generic programming is to
reinterpret the notation within a generic body through the parametric
meaning of that notation.  Today, for method invocations, that means
"call through the virtual function table".  That's certainly right for
tagged types.  It's too restrictive for other types.

My goal is to envision a reasonable way of introducing into visibility
all the affordances of a type with just the type name and not its
whole package of definition.  A hypothetical attribute such as
T'Package isn't the right thing, since it would expand visibility
(even if it were feasible to implement).

What about tagging the function rather than the type?  Imaginary
example:
    function Op( X : T ) return X is tagged ;
The sole purpose of the tag in this example is to mark a particular
function signature as available through "." notation.

Eric






^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  1:46       ` Randy Brukardt
@ 2008-03-14  9:00         ` Dmitry A. Kazakov
  2008-03-14 14:36           ` User-defined type attributes (replacing genericity) Georg Bauhaus
  2008-03-15  3:04           ` User-defined type attributes Randy Brukardt
  2008-03-14 14:31         ` User-defined type attributes (replacing genericity) Georg Bauhaus
  1 sibling, 2 replies; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-14  9:00 UTC (permalink / raw)


On Thu, 13 Mar 2008 20:46:41 -0500, Randy Brukardt wrote:

> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:965suhjl0bxt$.74se2ylyksin.dlg@40tude.net...
> ...
>> Why? The only thing you need is formal generic ADTs. Ada's generics lack
>> ADTs, which is the reason why you need to pass operations together with the
>> formal types. There exist formal built-in types like "private", "<>",
>> "digits <>" etc, but there is no user-defined ones. Add these and all
>> primitive operations will go with the actual type just per magic. It would
>> be IMO a natural step for anybody who wanted generics to evolve in an
>> Ada-way. (Not for me, as you know, I prefer generics removed from the
>> language.)
> 
> Generic formal derived types are the way to bring an ADT into a generic.
> After all, they do bring in all of the primitive operations of the ADT.
>
> The only problem is that they can't be used on unrelated types, but that's
> not very relevant if you are using tagged types (and you might as well being
> doing so if you're defining any sort of composite type).

Right, but this also implies that there is no need to have generics at all.
A class-wide object does all what needed:

   generic
      type S is new T with private;
   procedure Foo (X : in out S);

can be replaced by:

   procedure Foo (X : in out T'Class);

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  3:55       ` Eric Hughes
@ 2008-03-14  9:01         ` Dmitry A. Kazakov
  2008-03-14 18:04           ` Eric Hughes
  0 siblings, 1 reply; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-14  9:01 UTC (permalink / raw)


On Thu, 13 Mar 2008 20:55:27 -0700 (PDT), Eric Hughes wrote:

> On Mar 13, 1:58 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> In which sense function is static? If understand what you wrote, it simply
>> means that the name "Callable" is static.
> 
> That's not what I meant.  Here's some sample notation, whose syntax is
> merely illustrative.
> 
>     -- Declaration of an attribute
>     generic
>         task type T ;
>     function T'Callable return boolean ;
> 
>     -- Declaration of a (static) implementation function
>     generic
>         task type T ;
>     function Callable_Impl return access function( X : T ) return
> boolean is static ;

Hmm, what is static here? An instance of the body or the result of
execution of an instance? Let I declare T in a nested block, then
instantiate Callable_Impl there, would it go?

>     -- Binding of an implementation to an attribute
>     generic
>         task type T ;
>         Obj : T ;
>     for Obj'Callable use Callable_Impl.all( X => Obj ) ;
> 
> Regardless of whatever syntax is appropriate, one of the things that
> makes me uncomfortable about attributes is that their definitions
> don't have the same rigor of notation in their definitions as, say,
> the standard libraries do.

Right, because to make it rigorously you have to make "task type" a proper
class. That means, tasks must be tagged, there must be Root_Task type and a
class of. Then you could simply and rigorously write:

   function "'Callable" (T : Root_Task) return Boolean;

> In the spirit of separation compilation,
> I'd like to see attribute definitions in specification packages, even
> if their bodies exist solely within a compiler's implementation.

Sure. Nevertheless this or that way you have to be able to specify that a
body is static (contract on the implementation). That the body is pure (a
permission to derive static result from static arguments). Or do you want
compile-time bodies written in some other (meta) language, like they are in
C and PL/1 preprocessors?

> I wrote:
>> Functions on a type are part of the tradition algebraic
>> specification of a type.  Attributes on a type are part of the
>> language environment inside of which a type specification is
>> expressed.  These are very different.
> 
> "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de> wrote:
>> I don't see why this distinction is important.
> 
> I'm afraid I don't know how to argue this point briefly.  It's the
> difference between language (in the proof theory sense) and
> metalanguage.  I guess I've done too much formal logic too see this
> distinction and its import as anything other than obvious.

I see where you are going. It is to consider (some) attributes
automatically instantiated generic functions. Am I right?

That would be indeed a metalanguage. But I am quite uncomfortable with all
three: metalanguage, generics as one, automatic instantiation. As you said,
a metalanguage shall be clearly separated from the object one. This is the
reason why generics are bad, they slip through the barrier and exist at run
time. Similarly attributes inevitably will.

IMO it would much "simpler" (and more useful):

1. to make classes available for all types
2. to introduce pure and static bodies
3. to allow "'X" sugar for user-defined subprograms
4. to specify existing attributes in terms of 1..3.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14  1:46       ` Randy Brukardt
  2008-03-14  9:00         ` Dmitry A. Kazakov
@ 2008-03-14 14:31         ` Georg Bauhaus
  2008-03-14 14:48           ` Dmitry A. Kazakov
  2008-03-14 16:58           ` Georg Bauhaus
  1 sibling, 2 replies; 29+ messages in thread
From: Georg Bauhaus @ 2008-03-14 14:31 UTC (permalink / raw)



On Fri, 2008-03-14 at 10:00 +0100, Dmitry A. Kazakov wrote:

> Right, but this also implies that there is no need to have generics at all.
> A class-wide object does all what needed:
> 
>    generic
>       type S is new T with private;
>    procedure Foo (X : in out S);
> 
> can be replaced by:
> 
>    procedure Foo (X : in out T'Class);

I assume your answer to what follows will be that Ada semantics
should be put under programmer control, that range should be
and interface type, etc. ;-) But anyway, even that doesn't change
things.

I just looked at the effects. Not promising on two accounts,
but more rattling regularity. Which might have its place.

Replacing genericity means every generic instance is replaced
with an invocation of just one procedure. However, for objects of
specially crafted types. One type needs to be available for
mimicking each generic.

I had two types

    type Simple is range 1 .. 100;
    -- predefined "<="

    type Data is record
       amount: Natural;
       wpi: Float;
    end record;

    function "<="(a, b: Data) return Boolean;


According to the suggestion to abandon generics I have had instead,
basically,

   procedure Foo (X, Y, Z : in out T'Class) is
      function Is_Highest(V: T) return Boolean is
      begin
         return X <= V and then Y <= V and then Z <= V;
      end Is_Highest;
   begin
      ...


The comparison function "<=" needs to be one of the primitive
operations of all types in T'Class. (Hence a wrapper type becomes
necessary for range type Simple.)

(I'll leave out the problem of local variables of type T'Class.)
(I'll leave out required variance programming work, too.)

With generics, I got two nicely specialized instances of Foo,
one for the range type, the other for the composite type.
The effect is that function Is_Highest will use "<=" as I
would expect for a range type. Small code, obvious, and
efficient. Similarly, the "<=" of the Data instance's
Is_Highest function corresponds directly to both the definition
and to the expectation.

Without generics, there is only one Is_Highest, as might be
expected. 

Inlining did not help. In fact, I wouldn't expect inlining to be
readily available with 'Class---unless of course
replacing generics should also entail compilers that look at
the entire program. Then, maybe, a few more thing can be
"optimized" at compile time.






^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14  9:00         ` Dmitry A. Kazakov
@ 2008-03-14 14:36           ` Georg Bauhaus
  2008-03-15  3:04           ` User-defined type attributes Randy Brukardt
  1 sibling, 0 replies; 29+ messages in thread
From: Georg Bauhaus @ 2008-03-14 14:36 UTC (permalink / raw)



On Fri, 2008-03-14 at 15:31 +0100, Georg Bauhaus wrote:

> Without generics, there is only one Is_Highest, as might be
> expected. 
<Important-addendum>
A really general Is_Highest, even when looking at the
disassembly. There are computed addresses, indirect
references all over the listing, everything purely mechanical,
no trace of anything concrete. And not fast.</>





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 14:31         ` User-defined type attributes (replacing genericity) Georg Bauhaus
@ 2008-03-14 14:48           ` Dmitry A. Kazakov
  2008-03-14 17:51             ` Eric Hughes
  2008-03-14 16:58           ` Georg Bauhaus
  1 sibling, 1 reply; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-14 14:48 UTC (permalink / raw)


On Fri, 14 Mar 2008 15:31:40 +0100, Georg Bauhaus wrote:

> On Fri, 2008-03-14 at 10:00 +0100, Dmitry A. Kazakov wrote:
> 
>> Right, but this also implies that there is no need to have generics at all.
>> A class-wide object does all what needed:
>> 
>>    generic
>>       type S is new T with private;
>>    procedure Foo (X : in out S);
>> 
>> can be replaced by:
>> 
>>    procedure Foo (X : in out T'Class);
> 
> I assume your answer to what follows will be that Ada semantics
> should be put under programmer control,

What's wrong with having control over the semantics?

> that range should be and interface type, etc. ;-)

Shouldn't it?

> But anyway, even that doesn't change things.
> 
> I just looked at the effects. Not promising on two accounts,
> but more rattling regularity. Which might have its place.
> 
> Replacing genericity means every generic instance is replaced
> with an invocation of just one procedure.

No, only calls to instances of generic bodies.

> However, for objects of
> specially crafted types. One type needs to be available for
> mimicking each generic.
> 
> I had two types
> 
>     type Simple is range 1 .. 100;
>     -- predefined "<="
> 
>     type Data is record
>        amount: Natural;
>        wpi: Float;
>     end record;
> 
>     function "<="(a, b: Data) return Boolean;
> 
> According to the suggestion to abandon generics I have had instead,
> basically,
> 
>    procedure Foo (X, Y, Z : in out T'Class) is
>       function Is_Highest(V: T) return Boolean is
>       begin
>          return X <= V and then Y <= V and then Z <= V;
>       end Is_Highest;
>    begin
>       ...
> 
> The comparison function "<=" needs to be one of the primitive
> operations of all types in T'Class. (Hence a wrapper type becomes
> necessary for range type Simple.)

No, what you need is an interface implemented by both. You need to declare
Simple implementing Ordered. That will tell the compiler that the
predefined "<=" is an implementation of Ordered's "<=".

> (I'll leave out the problem of local variables of type T'Class.)
> (I'll leave out required variance programming work, too.)
> 
> With generics, I got two nicely specialized instances of Foo,
> one for the range type, the other for the composite type.
> The effect is that function Is_Highest will use "<=" as I
> would expect for a range type. Small code, obvious, and
> efficient. Similarly, the "<=" of the Data instance's
> Is_Highest function corresponds directly to both the definition
> and to the expectation.
> 
> Without generics, there is only one Is_Highest, as might be
> expected. 

Why there have to be two? The whole idea of generics was to have *one*
generic body. This is why it is called generic [programming].

> Inlining did not help. In fact, I wouldn't expect inlining to be
> readily available with 'Class---unless of course
> replacing generics should also entail compilers that look at
> the entire program. Then, maybe, a few more thing can be
> "optimized" at compile time.

You mixing two different problems. BTW, I answered both in my earlier
posts. So I repeat it short. If you want to constrain the dispatching table
to the diagonal you do it

   procedure Foo (X, Y, Z : in out T)

This requires X, Y, Z to have exactly same type. The language of
constraints is a different theme. Do not sell a limitation of generics to a
certain type of constraint as genuine advantage.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 14:31         ` User-defined type attributes (replacing genericity) Georg Bauhaus
  2008-03-14 14:48           ` Dmitry A. Kazakov
@ 2008-03-14 16:58           ` Georg Bauhaus
  2008-03-14 18:39             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 29+ messages in thread
From: Georg Bauhaus @ 2008-03-14 16:58 UTC (permalink / raw)


On Fri, 2008-03-14 at 15:48 +0100, Dmitry A. Kazakov wrote:

> > I assume your answer to what follows will be that Ada semantics
> > should be put under programmer control,
> 
> What's wrong with having control over the semantics?

(Control over the semantics of the language. I'm not a compiler,
and I'm not imagining I am as good as someone who can routinely
master the advanced parts of implementing Ada in user programs.
That is what I think will be wrong.

It is certainly possible to imagine some meta-flavoring for
Ada. But I don't want to inspect such pieces of sophistication
when they come out of the hands of ordinary programmers
and have errors. There will be at least one more
level of linguistic indirection between me and the LRM:
the programmer's language interpretation as implemented in
his semantics control.)


> No, what you need is an interface implemented by both. You need to declare
> Simple implementing Ordered. That will tell the compiler that the
> predefined "<=" is an implementation of Ordered's "<=".

Actually, it doesn't matter whether "<=" is predefined. It could
just as well have been a user defined "<=". The Foo(...'Class) would
have had one one general ("generic"?) implementation of Is_Highest,
as described. This Is_Highest will have no specialization, but
it will feature highly stylized indirection, dispatching to the
implementing code for the respective "<=".


> > Without generics, there is only one Is_Highest, as might be
> > expected. 
> 
> Why there have to be two? The whole idea of generics was to have *one*
> generic body. This is why it is called generic [programming].

I *can* have and I *did* have just one body in *source* code.
We both know that Ada does not anywhere require that generics
must not yield more than one lists of object code per
generic. This would seem like a stupid restriction, one that
I think no one has wanted to put in the minds of the language
makers.


> If you want to constrain the dispatching table
> to the diagonal

I don't want that language to inflict a dispatching table
on me when that offers no advantage at all!

- I don't need any dispatching here,
- My code is more efficient without it,
- Review of the generated code is simpler because
  there are fewer indirections.
- There still is abstraction.

If that doesn't count as advantages ...


>  Do not sell a limitation of generics to a
> certain type of constraint as genuine advantage.

>From looking at generated code, the genuine advantage seems
to be the total absence of dispatching code.
Absence of code whose major contribution can, by the impression
of the assembly listing, roughly be expressed as

 X.all.Call_Maker.all.Invoke

instead of

 X.all.Call

in the generic case





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 14:48           ` Dmitry A. Kazakov
@ 2008-03-14 17:51             ` Eric Hughes
  2008-03-14 18:58               ` Dmitry A. Kazakov
  2008-03-15  4:01               ` Randy Brukardt
  0 siblings, 2 replies; 29+ messages in thread
From: Eric Hughes @ 2008-03-14 17:51 UTC (permalink / raw)


On Fri, 14 Mar 2008 15:31:40 +0100, Georg Bauhaus wrote:
> Without generics, there is only one Is_Highest, as might be
> expected.

On Mar 14, 8:48 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> Why there have to be two? The whole idea of generics was to have *one*
> generic body. This is why it is called generic [programming].

Here's the nut of the problem.  There is one generic body in the code
of the programming language.  When you substitute type parameters into
that generic body, you get multiple different manifestations of that
original generic body, that is, multiple bodies, one for each type.
And that means multiple versions as translated into machine code.
This is indeed the primary desideratum of generic programming.  Having
said this, there's a standard technique of converting type operations
into virtual function calls.  I feel like I need to say this--these
aren't the same thing.  This allows the reduction of the manifestation
a generic body to a single canonical form.  This has a single version
in machine code.

A realistic system for generic programming should support both modes
of code generation.  This allows the developer to determine their own
answer to the code-size vs. performance trade-off.  Ada has already
taken the stance, as evidenced by representation clauses, that it will
support both high and low levels of abstraction.  Eliminating generics
would force everything into virtual function calls, choose code-size
over performance, and make that choice on behalf of every programmer.

If you go down the road of requiring all method calls to be virtual,
of requiring that there be run-time manifestations of all meta-
language features, you get Java.  Java has its place.  So does Ada.
These aren't the same place.

Eric





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  9:01         ` Dmitry A. Kazakov
@ 2008-03-14 18:04           ` Eric Hughes
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Hughes @ 2008-03-14 18:04 UTC (permalink / raw)


On Mar 14, 3:01 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> Right, because to make it rigorously you have to make "task type" a proper
> class. That means, tasks must be tagged, there must be Root_Task type and a
> class of.

No, you don't.  If your only conception of generic programming is to
virtualize everything, then this statement would be true to you.  But
this conclusion rests upon an invalid premise about the nature of
generic programming.

> I see where you are going. It is to consider (some) attributes
> automatically instantiated generic functions. Am I right?

Basically correct.  Yet I also mean generic functions in their full
sense and not in the sense where they are instantiated merely with
virtual function calls.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 16:58           ` Georg Bauhaus
@ 2008-03-14 18:39             ` Dmitry A. Kazakov
  2008-03-15  9:39               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-14 18:39 UTC (permalink / raw)


On Fri, 14 Mar 2008 17:58:46 +0100, Georg Bauhaus wrote:

> On Fri, 2008-03-14 at 15:48 +0100, Dmitry A. Kazakov wrote:
> 
>>> I assume your answer to what follows will be that Ada semantics
>>> should be put under programmer control,
>> 
>> What's wrong with having control over the semantics?
> 
> (Control over the semantics of the language. I'm not a compiler,
> and I'm not imagining I am as good as someone who can routinely
> master the advanced parts of implementing Ada in user programs.
> That is what I think will be wrong.

But the compiler is in an even worse position. It cannot know your intent
when you introduce a new operation, type, object etc. It is up to you to
define the semantics of.

> It is certainly possible to imagine some meta-flavoring for
> Ada. But I don't want to inspect such pieces of sophistication
> when they come out of the hands of ordinary programmers
> and have errors. There will be at least one more
> level of linguistic indirection between me and the LRM:
> the programmer's language interpretation as implemented in
> his semantics control.)

Sorry, but it is generics which constitute a meta language, so this
argument you should address to yourself.

Further, it seems that you believe that Ada defines some meta-level
semantics of attributes and operations like "+", "-", etc. But, it does
not. You can define "+" to perform multiplication or to act on tasks.

BUT, if you wanted to do that (I don't), then again the first step should
be away from generics, towards proper classes. For example, to define a
class of additive objects and to forbid use of "+" for anything outside the
class.

>> No, what you need is an interface implemented by both. You need to declare
>> Simple implementing Ordered. That will tell the compiler that the
>> predefined "<=" is an implementation of Ordered's "<=".
> 
> Actually, it doesn't matter whether "<=" is predefined. It could
> just as well have been a user defined "<=". The Foo(...'Class) would
> have had one one general ("generic"?) implementation of Is_Highest,
> as described. This Is_Highest will have no specialization, but
> it will feature highly stylized indirection, dispatching to the
> implementing code for the respective "<=".

In fact, your code will not compile. It should be:

   function Is_Highest (V: T'Class) return Boolean is
   begin
      return X <= V and then Y <= V and then Z <= V;
   end Is_Highest;

So what was the problem?

>>> Without generics, there is only one Is_Highest, as might be
>>> expected. 
>> 
>> Why there have to be two? The whole idea of generics was to have *one*
>> generic body. This is why it is called generic [programming].
> 
> I *can* have and I *did* have just one body in *source* code.

Yes this is what I meant.

> We both know that Ada does not anywhere require that generics
> must not yield more than one lists of object code per
> generic. This would seem like a stupid restriction, one that
> I think no one has wanted to put in the minds of the language
> makers.

I didn't meant the implementation. Semantically there is one body even if
instantiations expand it.

>> If you want to constrain the dispatching table to the diagonal
> 
> I don't want that language to inflict a dispatching table
> on me when that offers no advantage at all!

Dispatching table is not a physical object. It is a formal model to
describe operations defined on a class. Such polymorphic operations have
type-specific implementations (because the language is strongly typed). The
dispatching table lists them according to the order relation (subtyping) of
the types of the arguments. How and if to implement it is up to the
compiler.

> - I don't need any dispatching here,

You have to. Dispatch is a selection of a type-specific body responsible
for the implementation of a generic (polymorphic) one for the given
combination of argument types. When you instantiate a generic body it is an
act of dispatching, performed manually.

> - My code is more efficient without it,

It is not Ada's objective. Then with statically known types and inlined
bodies you could have the same code GNAT generics produce.

> - Review of the generated code is simpler because
>   there are fewer indirections.

I never review generated code. I wrote large (then) programs about 20K
SLOC, now I am using Ada, I don't want back.

> - There still is abstraction.

Where? In the object code?

>>  Do not sell a limitation of generics to a
>> certain type of constraint as genuine advantage.
> 
> From looking at generated code, the genuine advantage seems
> to be the total absence of dispatching code.

You don't need any code when dispatch is static.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 17:51             ` Eric Hughes
@ 2008-03-14 18:58               ` Dmitry A. Kazakov
  2008-03-14 20:19                 ` Eric Hughes
  2008-03-15  4:01               ` Randy Brukardt
  1 sibling, 1 reply; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-14 18:58 UTC (permalink / raw)


On Fri, 14 Mar 2008 10:51:25 -0700 (PDT), Eric Hughes wrote:

> On Fri, 14 Mar 2008 15:31:40 +0100, Georg Bauhaus wrote:
>> Without generics, there is only one Is_Highest, as might be
>> expected.
> 
> On Mar 14, 8:48 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> Why there have to be two? The whole idea of generics was to have *one*
>> generic body. This is why it is called generic [programming].
> 
> Here's the nut of the problem.  There is one generic body in the code
> of the programming language.  When you substitute type parameters into
> that generic body, you get multiple different manifestations of that
> original generic body, that is, multiple bodies, one for each type.
> And that means multiple versions as translated into machine code.

No, Ada is not like that. In fact much efforts, at least in Ada 83, was
paid in order to allow sharing of generic bodies. AFAIK, Janus Ada shares
them.

> This is indeed the primary desideratum of generic programming.  Having
> said this, there's a standard technique of converting type operations
> into virtual function calls.  I feel like I need to say this--these
> aren't the same thing.  This allows the reduction of the manifestation
> a generic body to a single canonical form.  This has a single version
> in machine code.

It is optimization technique. You could instruct the compiler to inline a
class-wide body. You could require to generate a separate instance for each
used combination of argument types. Semantically the body is still same.

> A realistic system for generic programming should support both modes
> of code generation.  This allows the developer to determine their own
> answer to the code-size vs. performance trade-off.  Ada has already
> taken the stance, as evidenced by representation clauses, that it will
> support both high and low levels of abstraction.

If that were true it would be a premature optimization. Anyway semantically
there is no any difference between generic and class-wide bodies. Both act
on a class of types.

To be honest, there are formal generic parameters beyond types:

1. Formal objects. These are not required and covered by plain functions.
Normally they are used to work around language limitations, usually in
types algebra, which is the weak point.

2. Formal packages. This looks like a useful thing, but child packages and
better classes might make them superfluous.

> Eliminating generics
> would force everything into virtual function calls, choose code-size
> over performance, and make that choice on behalf of every programmer.
> If you go down the road of requiring all method calls to be virtual,

Note that class-wide bodies do not dispatch.

> of requiring that there be run-time manifestations of all meta-
> language features, you get Java.  Java has its place.  So does Ada.
> These aren't the same place.

Similarly I could argue that Ada generics (at least as you an George
describe them) is a preprocessor. There are many. Right, they are poorly
designed, untyped etc. But who said that Java was designed properly?

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 18:58               ` Dmitry A. Kazakov
@ 2008-03-14 20:19                 ` Eric Hughes
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Hughes @ 2008-03-14 20:19 UTC (permalink / raw)


On Mar 14, 12:58 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> Anyway semantically
> there is no any difference between generic and class-wide bodies. Both act
> on a class of types.

Not every similarity between types is also a class-wide similarity.
Without this essential distinction, I cannot begin to have a useful
discussion about generics.

I'm out.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  9:00         ` Dmitry A. Kazakov
  2008-03-14 14:36           ` User-defined type attributes (replacing genericity) Georg Bauhaus
@ 2008-03-15  3:04           ` Randy Brukardt
  2008-03-15  9:33             ` Dmitry A. Kazakov
  1 sibling, 1 reply; 29+ messages in thread
From: Randy Brukardt @ 2008-03-15  3:04 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
news:pqup5kf1u34t$.19kwms4bw12hs.dlg@40tude.net...
> On Thu, 13 Mar 2008 20:46:41 -0500, Randy Brukardt wrote:
>
> > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> > news:965suhjl0bxt$.74se2ylyksin.dlg@40tude.net...
> > ...
> >> Why? The only thing you need is formal generic ADTs. Ada's generics
lack
> >> ADTs, which is the reason why you need to pass operations together with
the
> >> formal types. There exist formal built-in types like "private", "<>",
> >> "digits <>" etc, but there is no user-defined ones. Add these and all
> >> primitive operations will go with the actual type just per magic. It
would
> >> be IMO a natural step for anybody who wanted generics to evolve in an
> >> Ada-way. (Not for me, as you know, I prefer generics removed from the
> >> language.)
> >
> > Generic formal derived types are the way to bring an ADT into a generic.
> > After all, they do bring in all of the primitive operations of the ADT.
> >
> > The only problem is that they can't be used on unrelated types, but
that's
> > not very relevant if you are using tagged types (and you might as well
being
> > doing so if you're defining any sort of composite type).
>
> Right, but this also implies that there is no need to have generics at
all.
> A class-wide object does all what needed:
>
>    generic
>       type S is new T with private;
>    procedure Foo (X : in out S);
>
> can be replaced by:
>
>    procedure Foo (X : in out T'Class);

Not if you need other generic parameters along with the type. And this is a
way to do mixins, which otherwise can't be done in Ada 95 because type can't
derive from a class-wide type:

   generic
      type S is new T with private;
   package Foo is
      type New_S is new S with private;
      procedure New_Operation (Op : in out New_S);
   end Foo;

It's a nice way to add persistence, for instance. (Interfaces only allow you
to add, umm, interfaces, not code.)

                     Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-14  4:41   ` Eric Hughes
@ 2008-03-15  3:20     ` Randy Brukardt
  2008-03-17  4:38       ` Eric Hughes
  0 siblings, 1 reply; 29+ messages in thread
From: Randy Brukardt @ 2008-03-15  3:20 UTC (permalink / raw)


"Eric Hughes" <eric.eh9@gmail.com> wrote in message
news:928f737d-955f-415b-93b1-ddbd24fbf81e@e25g2000prg.googlegroups.com...
> On Mar 13, 7:46 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
...
> > That's OK, because only tagged types work "right" in Ada. [...]
> >
> > Thus, I think virtually all new composite types should be tagged in Ada
> > programs [...]
>
> I'm with you on the general idea.  In my own code, most of my types
> are tagged.  But the requirement to have them tagged in order to use
> the "." operator forces a trade-off: either (a) restrict generic
> parameters to tagged types or (b) avoid "." notation and be required
> to pull in whole packages rather than only single types.  This doesn't
> match up with the separation of concerns (a.k.a. orthogonality) which
> is one of the hallmarks of Ada and one of the things I appreciate most
> about the language.

I agree. Indeed, that is a frequent gripe that we (the ARG) have, and
something we try to avoid introducing more of. But I doubt that it can
really be fixed, simply because of compatibility. We can't change the
semantics of existing programs in ways that would break much of the existing
Ada code. We went about as far as we would ever go that way with the
deletion of return-by-reference in the Amendment. And there was a lot of
concern that we went too far (but I think that most people have agreed that
the pain was worth the benefits).

It's the problem that occurs when you're working on something with a
substantial installed base, be it a programming language, compiler, or OS.
You don't get a blank page; you have to support most of what went before.
Witness Microsoft's problems with Windows Vista as an example of what can
happen if you don't pay attention to it.

Thus you get things like tagged types which simply work better than other
kinds of types. That was introduced in Ada 95, and we have been happy to
continue it going forward.

In any case, I don't think a massive overhaul in this (or any other area) is
very likely for Ada. Even if the result would make more sense.

                          Randy.



  The power of generic programming is to
> reinterpret the notation within a generic body through the parametric
> meaning of that notation.  Today, for method invocations, that means
> "call through the virtual function table".  That's certainly right for
> tagged types.  It's too restrictive for other types.
>
> My goal is to envision a reasonable way of introducing into visibility
> all the affordances of a type with just the type name and not its
> whole package of definition.  A hypothetical attribute such as
> T'Package isn't the right thing, since it would expand visibility
> (even if it were feasible to implement).
>
> What about tagging the function rather than the type?  Imaginary
> example:
>     function Op( X : T ) return X is tagged ;
> The sole purpose of the tag in this example is to mark a particular
> function signature as available through "." notation.
>
> Eric
>
>
>





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 17:51             ` Eric Hughes
  2008-03-14 18:58               ` Dmitry A. Kazakov
@ 2008-03-15  4:01               ` Randy Brukardt
  1 sibling, 0 replies; 29+ messages in thread
From: Randy Brukardt @ 2008-03-15  4:01 UTC (permalink / raw)


"Eric Hughes" <eric.eh9@gmail.com> wrote in message
news:821256cd-2d20-46dd-92d2-cdd21181dbb8@s8g2000prg.googlegroups.com...
> On Mar 14, 8:48 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
> > Why there have to be two? The whole idea of generics was to have *one*
> > generic body. This is why it is called generic [programming].
>
> Here's the nut of the problem.  There is one generic body in the code
> of the programming language.  When you substitute type parameters into
> that generic body, you get multiple different manifestations of that
> original generic body, that is, multiple bodies, one for each type.
> And that means multiple versions as translated into machine code.

That has nothing whatsoever to do with Ada. Most Ada implementations work
that way, but there is no requirement that they do. Indeed, there are a lot
of rules in Ada specifically to allow the sharing of generic bodies. A
number of Ada 83 compilers used to do it as a matter of course; Janus/Ada is
the only one that I know that still does for Ada 95 and later.

This sort of performance is best handled by inlining, IMHO. It's virtually
impossible to share something that is generated separately (I know, I did
that extensively to shoehorn our compilers onto Z80s back in the dark ages);
it's a lot easier to "unshare" something that is shared than the reverse.

Janus/Ada was designed around this plan; unfortunately, circumstances (and
the underpowered machines of the late 1980's and early 1990's) meant that
the inlining linker never got built. It actually wouldn't be all that much
work (I think a couple of man-months), but it is still too much to tackle at
the moment.

> A realistic system for generic programming should support both modes
> of code generation.  This allows the developer to determine their own
> answer to the code-size vs. performance trade-off.

Actually, much of the time the compiler has a pretty good idea. All it needs
are some hints.

This is one thing that Java compilers have over Ada ones, because the Java
program usually already has been running a while before it is compiled, so
the areas that need to be concentrated on for speed are known.

In any case, 95% of programs are fast enough without any fancy optimization.
And 4% of the rest don't need much. Most people spend way too much time
worrying about the last 1% (probably because it is more interesting than
getting work done -- just like answering your note is. ;-)

> Ada has already taken the stance, as evidenced by representation clauses,
> that it will support both high and low levels of abstraction.  Eliminating
generics
> would force everything into virtual function calls, choose code-size
> over performance, and make that choice on behalf of every programmer.

Yup, and that probably would be the right choice most of the time. Moreover,
there is no problem using static binding, partial evaluation, and inlining
to get rid of the majority of the virtual overhead. Remember, Ada statically
binds calls to tagged types; it's pretty hard to write dispatching calls.

(I know of a number of bugs in that area in Janus/Ada, yet no one has yet
written a program that has hit any of them. Or at least they've never
reported them. Obviously, they're not that high of a priority to get
fixed...)

> If you go down the road of requiring all method calls to be virtual,
> of requiring that there be run-time manifestations of all meta-
> language features, you get Java.  Java has its place.  So does Ada.
> These aren't the same place.

How you compile makes all the difference. The language doesn't make that
much (it does make some), as long as there is reasonably strong typing so
that calls can be statically bound. But I realize few people agree with me
on this; had we actually been able to build the entire compiler system that
we had envisioned (with C and Ada front-ends, and three backends: checkout
interpreter, conventional fast compiler, and highly optimizing link-time
compiler) I suspect that either a lot more people would agree or no one
(including me) would.

                               Randy.






^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-15  3:04           ` User-defined type attributes Randy Brukardt
@ 2008-03-15  9:33             ` Dmitry A. Kazakov
  0 siblings, 0 replies; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-15  9:33 UTC (permalink / raw)


On Fri, 14 Mar 2008 22:04:53 -0500, Randy Brukardt wrote:

> Not if you need other generic parameters along with the type. And this is a
> way to do mixins, which otherwise can't be done in Ada 95 because type can't
> derive from a class-wide type:
> 
>    generic
>       type S is new T with private;
>    package Foo is
>       type New_S is new S with private;
>       procedure New_Operation (Op : in out New_S);
>    end Foo;
> 
> It's a nice way to add persistence, for instance. (Interfaces only allow you
> to add, umm, interfaces, not code.)

Speaking of language enhancements proper multiple inheritance would be a
better way to do this.

But actually I would like to have "supertypes" in order to be able to add
interfaces and code to existing types:

   type T is ...;  -- Defined independently on Persistent

   type Persistent is abstract...; -- Oops, we forgot to do it before T

   type Bridge is new Persistent and old T; --- (:-))

Bridge is a subtype of Persistent and a supertype of T. This injects
Bridge's implementation of Persistent into T within Bridge's scope.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes (replacing genericity)
  2008-03-14 18:39             ` Dmitry A. Kazakov
@ 2008-03-15  9:39               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 29+ messages in thread
From: Dmitry A. Kazakov @ 2008-03-15  9:39 UTC (permalink / raw)


On Fri, 14 Mar 2008 19:39:57 +0100, Dmitry A. Kazakov wrote:

> I never review generated code. I wrote large (then) programs about 20K
> SLOC,

in assembler, I mean.

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



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-15  3:20     ` Randy Brukardt
@ 2008-03-17  4:38       ` Eric Hughes
  2008-03-17 21:03         ` Randy Brukardt
  0 siblings, 1 reply; 29+ messages in thread
From: Eric Hughes @ 2008-03-17  4:38 UTC (permalink / raw)


On Mar 14, 9:20 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> Indeed, that is a frequent gripe that we (the ARG) have, and
> something we try to avoid introducing more of. But I doubt that it can
> really be fixed, simply because of compatibility. We can't change the
> semantics of existing programs in ways that would break much of the existing
> Ada code.

Well, I don't think any of the ideas I've had recently about dot-
notation are in the realm of changing pre-existing semantics.
Instead, I'm concerned with keeping existing syntax patterns,
enlarging the domain of applicability of that syntax, and creating new
semantics that match existing practice.  While that becomes more
difficult as time goes forward, I think Ada's been pretty good about
making conservative choices that attenuate the consequences of
otherwise-rash decisions.

> Thus you get things like tagged types which simply work better than other
> kinds of types. That was introduced in Ada 95, and we have been happy to
> continue it going forward.

Tagged types do work better, sure.  But they're not a panacea,
either.  It would a mistake to address other difficulties with types
by shoehorning "solutions" to them into tags.  And in the last couple
of days I've realized the problems with untagged types as formal
parameters is much greater than the absence of dot-notation.

So here's a brief example.  I'm writing a smart accessor package set
right now.  As something of an exercise, I'm doing this as generically
as possible.  So I'm looking to write code that can use both intrusive
(part of the managed object) and accretive (separate from the managed
object) allocation strategies for reference counts.  And I want to do
it without making the accessor types tagged.  Since an intrusive
accessor is simple a wrapped-up access object, adding a tag would
double the machine size of an object.  I consider this a poor result
for a system-level library.

My first foray at solving this was to use a formal type parameter for
the implementation of the accessor.  The intrusive implementation
would contain just an access object; the accretive one would have that
plus an access to a reference count.  Pretty simple, so I thought.
But without using a tagged type in the formal parameter definition,
there's no visibility either for record components or for implicit
visibility of operators on that type.  Thus I couldn't get at
components either directly or indirectly.  I discarded that approach.

It's a shame really, because it would otherwise be a natural
representation of variety of in possible implementations.  I'm still
looking at other ways of approaching the problem.  I'm beginning to
suspect that doing this may be impossible, but I don't have an
argument yet.

Eric



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-17  4:38       ` Eric Hughes
@ 2008-03-17 21:03         ` Randy Brukardt
  2008-03-17 21:58           ` Eric Hughes
  0 siblings, 1 reply; 29+ messages in thread
From: Randy Brukardt @ 2008-03-17 21:03 UTC (permalink / raw)


"Eric Hughes" <eric.eh9@gmail.com> wrote in message
news:c6b7e0b5-6b81-486a-8054-becd0df9842b@h11g2000prf.googlegroups.com...
...
> Tagged types do work better, sure.  But they're not a panacea,
> either.  It would a mistake to address other difficulties with types
> by shoehorning "solutions" to them into tags.  And in the last couple
> of days I've realized the problems with untagged types as formal
> parameters is much greater than the absence of dot-notation.
>
> So here's a brief example.  I'm writing a smart accessor package set
> right now.  As something of an exercise, I'm doing this as generically
> as possible.  So I'm looking to write code that can use both intrusive
> (part of the managed object) and accretive (separate from the managed
> object) allocation strategies for reference counts.  And I want to do
> it without making the accessor types tagged.  Since an intrusive
> accessor is simple a wrapped-up access object, adding a tag would
> double the machine size of an object.  I consider this a poor result
> for a system-level library.
>
> My first foray at solving this was to use a formal type parameter for
> the implementation of the accessor.  The intrusive implementation
> would contain just an access object; the accretive one would have that
> plus an access to a reference count.  Pretty simple, so I thought.
> But without using a tagged type in the formal parameter definition,
> there's no visibility either for record components or for implicit
> visibility of operators on that type.  Thus I couldn't get at
> components either directly or indirectly.  I discarded that approach.
>
> It's a shame really, because it would otherwise be a natural
> representation of variety of in possible implementations.  I'm still
> looking at other ways of approaching the problem.  I'm beginning to
> suspect that doing this may be impossible, but I don't have an
> argument yet.

In cases like these, you have to pass accessor routines explicitly.
Something like:

generic
     type T is private;
     procedure Increment_Count (Obj : in out T) is <>;
     function Count (Obj : in T) is <>:
     ...
package Whatever is ...

Note the use of <> in these formal subprogram declarations. It gives a
default for the subprograms such that a routine with the right name and
profile automatically matches. (Why you can't have such defaults for types
is unknown by me...) This makes the instantiations less annoying (but you do
need to declare the appropriate routines somewhere).

You can wrap these things up and use them as formal packages if they are
common, so you don't necessarily have to end up with lots of generics with a
hundred parameters.

I would prefer to use an interface or tagged type here, but obviously you
can't do that. This is not a perfect solution, but it works and is commonly
used.

                                  Randy.





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: User-defined type attributes
  2008-03-17 21:03         ` Randy Brukardt
@ 2008-03-17 21:58           ` Eric Hughes
  0 siblings, 0 replies; 29+ messages in thread
From: Eric Hughes @ 2008-03-17 21:58 UTC (permalink / raw)


On Mar 17, 3:03 pm, "Randy Brukardt" <ra...@rrsoftware.com> wrote:
> In cases like these, you have to pass accessor routines explicitly.

Yeah, I figured that out this morning.  I should know better to post
at the end of the day before I've slept on it.

> It gives a
> default for the subprograms [...] (Why you can't have such defaults for types
> is unknown by me...)

Yeah, we just had that discussion two weeks ago.

> I would prefer to use an interface or tagged type here, but obviously you
> can't do that. This is not a perfect solution, but it works and is commonly
> used.

Notationally, it would be better, sure.  The problem, as you
acknowledge, is that it's a bad idea for a system library to require
any particular inheritance in order to work.  Working on this little
project has given substance to an idea I've had for a while about non-
inheritance type relationships.  In brief, it's to give a name to the
set of types that satisfy a certain set of signatures that,
critically, need _not_ be sufficient to form an abstract type.  This
specification constitutes a partial type.  To pick a simple example,
the set of trichotomous types is that which have a total ordering that
satisfy the standard trichotomy axioms (\forall a,b : a < b \land b <
a \implies a = b).  Trichotomy is a partial type.  It's a natural
parameter for generic ordered containers.

Indeed, partial types are the natural kind of formal type parameter
for any generic.  Right now in Ada they have to be simulated by
passing some set of formal parameters.  The spirit of Ada would be
better served by giving them an explicit representation.

Eric





^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2008-03-17 21:58 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-12 18:58 User-defined type attributes Eric Hughes
2008-03-12 21:23 ` Dmitry A. Kazakov
2008-03-13 18:32   ` Eric Hughes
2008-03-13 19:58     ` Dmitry A. Kazakov
2008-03-14  1:46       ` Randy Brukardt
2008-03-14  1:46       ` Randy Brukardt
2008-03-14  9:00         ` Dmitry A. Kazakov
2008-03-14 14:36           ` User-defined type attributes (replacing genericity) Georg Bauhaus
2008-03-15  3:04           ` User-defined type attributes Randy Brukardt
2008-03-15  9:33             ` Dmitry A. Kazakov
2008-03-14 14:31         ` User-defined type attributes (replacing genericity) Georg Bauhaus
2008-03-14 14:48           ` Dmitry A. Kazakov
2008-03-14 17:51             ` Eric Hughes
2008-03-14 18:58               ` Dmitry A. Kazakov
2008-03-14 20:19                 ` Eric Hughes
2008-03-15  4:01               ` Randy Brukardt
2008-03-14 16:58           ` Georg Bauhaus
2008-03-14 18:39             ` Dmitry A. Kazakov
2008-03-15  9:39               ` Dmitry A. Kazakov
2008-03-14  1:46       ` User-defined type attributes Randy Brukardt
2008-03-14  3:55       ` Eric Hughes
2008-03-14  9:01         ` Dmitry A. Kazakov
2008-03-14 18:04           ` Eric Hughes
2008-03-14  1:46 ` Randy Brukardt
2008-03-14  4:41   ` Eric Hughes
2008-03-15  3:20     ` Randy Brukardt
2008-03-17  4:38       ` Eric Hughes
2008-03-17 21:03         ` Randy Brukardt
2008-03-17 21:58           ` Eric Hughes

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