comp.lang.ada
 help / color / mirror / Atom feed
From: "Randy Brukardt" <randy@rrsoftware.com>
Subject: Re: T'Interface attribute
Date: Fri, 4 Aug 2017 18:51:45 -0500
Date: 2017-08-04T18:51:45-05:00	[thread overview]
Message-ID: <om31ai$ecu$1@franka.jacob-sparre.dk> (raw)
In-Reply-To: oluj7t$8uo$1@gioia.aioe.org

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:oluj7t$8uo$1@gioia.aioe.org...
> On 2017-08-03 06:46, Randy Brukardt wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:olskua$1bfd$1@gioia.aioe.org...
>>> In order to reduce name space contamination I would propose attribute
>>> T'Interface which for any tagged type T would denote an interface type
>>> with all *new* primitive operations, e.g.
>>
>> Past experience say that such attributes (that is, those that designate 
>> some
>> sort of type or subtype) don't work out very well in Ada. For instance, 
>> we
>> considered T'Access in Ada 2005, but gave that up because of various
>> problems (and replaced with with anonymous access types, which are 
>> worse).
>> The worst problem was that there was no limit to the attribute, you could
>> write T'Access'Access'Access - and you can't prevent this since T could 
>> be a
>> generic formal type that itself is some T'Access.
>
> In this case generic would not be a problem because T must be tagged to 
> have T'Interface.
>
> As a side note, differently to 'Access, 'Length and actually 'Class, 
> 'Interface is idempotent:
>
>    T'Interface ::= T'Interface'Interface

Ada defines 'Class this way, too, I think in part to mitigate these 
problems.

The problem with formals is from the actual being T'Interface:

    generic
       type T is abstract tagged private;
    package Gen is
        procedure P (Item : in T'Interface);
    end Gen;

    package Inst is new Gen (Some_Tagged_Type'Interface);

The parameter of P is essentially Some_Tagged_Type'Interface'Interface.

>> Almost all Ada compilers materialize all Ada types in their symbol table, 
>> so
>> the effect of having a T'Interface would be that it would be 
>> automatically
>> declared for all tagged type declarations. Most Ada compilers also
>> materialize all of the primitive operations in their symbol table, so 
>> there
>> would be a large increase in memory usage and some time increase (all
>> lookups would have twice as many primitives to look through).
>
> This is an intended effect. Yes, there would likely be two tags for each 
> declared type.
>
> Which by the way will fix Ada.Streams and System.Storage_Pools design for 
> free. Since we will finally have:
>
>    Root_Stream_Type'Interface
>
> and
>
>    Root_Storage_Pool'Interface
>
> E.g.
>
>    type Serialized_Widget is
>       new Gtk_Widget_Record and Root_Stream_Type'Interface with private;

The problem with "fixing" Root_Stream_Type etc. is the "no hidden 
interfaces" rule. These types are often used in private derivations, and 
that is illegal for interfaces. (Attempts to weaken the "no hidden 
interfaces" rule have led to various definitional nightmares - it does not 
look likely. AI12-0023-1 discusses the latest attempts - it's still open but 
hasn't been discussed since Stockholm.)

That suggests a problem with this idea: effectivelly all types would have an 
associated interface. But interfaces can never be hidden (certainly not 
without restrictions as discussed in AI12-0023-1), so that would seem to 
imply that no hidden type derivations could occur. That would be a massive 
compatibility problem.

>> P.S. And as always, explain the problem to be solved as well as the 
>> possible
>> solution. That is always necessary to understand the value of a proposal.
>
> I have a design rule to have an explicit interface declared for each 
> tagged type. It saves much of redesign later.

I've generally materialized that as "the root of an abstraction should 
always be declared abstract".

>> P.P.S. I personally have never seen a real-world example where an 
>> interface
>> actually helps. There's lots and lots of book examples and show examples 
>> and
>> so on, but in practice you end up with only a single implementation so 
>> there
>> really is nothing gained by involving a lot of dispatching calls. Ergo, 
>> I'm
>> against anything (new) involving interfaces. YMMV.
>
> I have no idea how you manage keep Claw out of interfaces, really. 
> Multiple inheritance is a huge help and relief. I am using interfaces 
> extensively unless backward Ada 95 compatibility hinders me. E.g. in AICWL 
> all widget layers implement interfaces like Scalable_Layer, Gauge_Needle, 
> Waveform_Amplifier etc. It would not work otherwise.

In Claw, the only places that we got much benefit from OOP (beyond 
dispatching callbacks, the reason we used OOP in the first place) was in 
sharing implementations across related types. But that doesn't work for Ada 
interfaces, because you can't have any components in the type -- meaning 
that writing real implementations is impossible. One can use abstract types 
in this way (and we did so extensively).

We didn't find much use for dispatching (outside of the callbacks as 
previously mentioned; those only need to work on root types since they come 
directly from the message loop engine). If you don't need (or can use) 
dispatching, and since you can't use implementation inheritance, the use of 
interfaces buys nothing.

(Of course, we didn't have interfaces when Claw was designed, so it wasn't 
even an option. Perhaps we'd have done something differently had they been 
available -- but I doubt it.)

That pattern has persisted in pretty much all of my recent programs; I don't 
usually have very deep hierarchies and dispatching is limited to the root 
types (which I declare abstract for maximum sharing).

I realize other people end up with other patterns, but I'm not going to 
champion something I don't find useful. (I doubt I could do a good job of 
championing it anyway).

                                       Randy.



  reply	other threads:[~2017-08-04 23:51 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-02 13:43 T'Interface attribute Dmitry A. Kazakov
2017-08-02 14:23 ` Eryndlia Mavourneen
2017-08-03 12:52   ` Dmitry A. Kazakov
2017-08-03  4:46 ` Randy Brukardt
2017-08-03  7:26   ` Dmitry A. Kazakov
2017-08-04 23:51     ` Randy Brukardt [this message]
2017-08-05  7:49       ` Dmitry A. Kazakov
2017-08-07 22:59         ` Randy Brukardt
2017-08-08  6:13           ` Dmitry A. Kazakov
2017-08-09  0:38             ` Randy Brukardt
2017-08-09  7:06               ` Dmitry A. Kazakov
2017-08-09 23:03                 ` Randy Brukardt
2017-08-10  7:13                   ` Dmitry A. Kazakov
2017-08-11  0:33                     ` Randy Brukardt
2017-08-11  6:55                       ` Dmitry A. Kazakov
2017-08-11 20:49                         ` Randy Brukardt
2017-08-03 17:27   ` Eryndlia Mavourneen
2017-08-05  0:09     ` Randy Brukardt
2017-08-05 19:02       ` Eryndlia Mavourneen
2017-08-07 22:49         ` 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