* T'Interface attribute @ 2017-08-02 13:43 Dmitry A. Kazakov 2017-08-02 14:23 ` Eryndlia Mavourneen 2017-08-03 4:46 ` Randy Brukardt 0 siblings, 2 replies; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-02 13:43 UTC (permalink / raw) 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. type Derived is new Parent with ...; not overriding procedure Foo (X : Derived); is equivalent to type Derived'Interface is [limited etc] interface; procedure Foo (X : Derived'Interface); type Derived is new Parent and Derived'Interface with ...; T'Interface is visible at the declaration point of T. Its use is same as of T. E.g. prior to the freezing point of T is "premature". Question. If T has any discriminants so does T'Interface. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 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 1 sibling, 1 reply; 20+ messages in thread From: Eryndlia Mavourneen @ 2017-08-02 14:23 UTC (permalink / raw) On Wednesday, August 2, 2017 at 8:43:41 AM UTC-5, Dmitry A. Kazakov wrote: > 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. > > type Derived is new Parent with ...; > not overriding procedure Foo (X : Derived); > > is equivalent to > > type Derived'Interface is [limited etc] interface; > procedure Foo (X : Derived'Interface); > > type Derived is new Parent and Derived'Interface with ...; > > T'Interface is visible at the declaration point of T. Its use is same as > of T. E.g. prior to the freezing point of T is "premature". > > Question. If T has any discriminants so does T'Interface. > > -- > Regards, > Dmitry A. Kazakov > http://www.dmitry-kazakov.de I believe this is a good idea. Regarding discriminants: Yes, they should extend to T'Interface, and T'Interface should be able to add discriminants, as desired/necessary. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-02 14:23 ` Eryndlia Mavourneen @ 2017-08-03 12:52 ` Dmitry A. Kazakov 0 siblings, 0 replies; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-03 12:52 UTC (permalink / raw) On 2017-08-02 16:23, Eryndlia Mavourneen wrote: > Regarding discriminants: Yes, they should extend to T'Interface, and > T'Interface should be able to add discriminants, as > desired/necessary. Yes. It seems that if T is an interface, then T and T'Interface must be same exactly types. Therefore discriminants must be retained. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-02 13:43 T'Interface attribute Dmitry A. Kazakov 2017-08-02 14:23 ` Eryndlia Mavourneen @ 2017-08-03 4:46 ` Randy Brukardt 2017-08-03 7:26 ` Dmitry A. Kazakov 2017-08-03 17:27 ` Eryndlia Mavourneen 1 sibling, 2 replies; 20+ messages in thread From: Randy Brukardt @ 2017-08-03 4:46 UTC (permalink / raw) "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. 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). All that said, it may make sense to work out the details; clearly an interface (which is indefinite) has less of these issues than an elementary type like T'Access. But I'm certain that it would have a distributed overhead on a compiler (maybe not as much of a concern as a distributed overhead on a compiled program, but it still matters). Randy. 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. 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. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-03 4:46 ` Randy Brukardt @ 2017-08-03 7:26 ` Dmitry A. Kazakov 2017-08-04 23:51 ` Randy Brukardt 2017-08-03 17:27 ` Eryndlia Mavourneen 1 sibling, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-03 7:26 UTC (permalink / raw) 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 > 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; > 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. > 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. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-03 7:26 ` Dmitry A. Kazakov @ 2017-08-04 23:51 ` Randy Brukardt 2017-08-05 7:49 ` Dmitry A. Kazakov 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-04 23:51 UTC (permalink / raw) "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. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-04 23:51 ` Randy Brukardt @ 2017-08-05 7:49 ` Dmitry A. Kazakov 2017-08-07 22:59 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-05 7:49 UTC (permalink / raw) On 2017-08-05 01:51, Randy Brukardt wrote: > "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. But P is not primitive. So effectively it can be compiled into procedure P (Item : in T); There is no requirement on what would evaluate this: package body Gen is function Check (X : T'Interface; Y : T) return Boolean begin return X'Tag = Y'Tag; end Check; > 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. Yes, you mean this: type I is interface; type T is new I with null record; type S is tagged private; private type S is new T with null record; -- Illegal? Come on! This mess should be fixed someday. BTW, there is nothing wrong with hidden interfaces. There apparent problems come from an misunderstanding, IMO. There is nothing wrong with additive inheritance. The same interface when added twice once publicly once privately could simply allocate new slots. In all contexts where both become visible must require explicit name resolution, e.g. by renaming one of the types and/or primitive operations. The typical use-case is a linked list interface, when elements participate in several lists. type Linked is limited interface; function Next (Element : Linked) return Linked; ... type Triple_Queue is new Linked or Linked or Linked with ... >>> 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". Yes, but this is not enough, because it kills potential multiple-inheritance cases. > 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). Reuse happens on the client's side, when you share interface-wide implementations. This includes helper types which refer to [access] I'Class. Surely you have lots of them to pass widgets around, in events, in handlers etc. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-05 7:49 ` Dmitry A. Kazakov @ 2017-08-07 22:59 ` Randy Brukardt 2017-08-08 6:13 ` Dmitry A. Kazakov 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-07 22:59 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:om3ta9$fnc$1@gioia.aioe.org... ... > There is nothing wrong with additive inheritance. The same interface when > added twice once publicly once privately could simply allocate new slots. We tried that. But... >... In all contexts where both become visible must require explicit name >resolution, e.g. by renaming one of the types and/or primitive operations. Ada doesn't have type renaming, so this is not possible in general. And having calls be illegal in such cases is a massive problem in generic bodies. Typical assume-the-worst rules would have to make calling any interface related to a formal illegal in a generic body. It was a massive can of worms. The alternative approach (the interface is the same) breaks privacy pretty badly. We essentially gave up, and more recent attempts to allow a limited set of "hidable interfaces" didn't fare any better. ... ... >> I've generally materialized that as "the root of an abstraction should >> always be declared abstract". > > Yes, but this is not enough, because it kills potential > multiple-inheritance cases. As an implementer, knowing that multiple-inheritance is just barely possible to implement, I'm unwilling to consider that unless no other possibility exists. And some other way always exists. :-) >> 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). > > Reuse happens on the client's side, when you share interface-wide > implementations. This includes helper types which refer to [access] > I'Class. Surely you have lots of them to pass widgets around, in events, > in handlers etc. Not really. The implementation has such things, but we only exposed parameters of Root_Window_Type'Class (with a couple of exceptions). The vast majority of routines only take a single object. The other hierarchies (canvas, menus, etc.) work similarly. Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-07 22:59 ` Randy Brukardt @ 2017-08-08 6:13 ` Dmitry A. Kazakov 2017-08-09 0:38 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-08 6:13 UTC (permalink / raw) On 2017-08-08 00:59, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> ... In all contexts where both become visible must require explicit name >> resolution, e.g. by renaming one of the types and/or primitive operations. > > Ada doesn't have type renaming, so this is not possible in general. Not exactly renaming, but a schema to qualify the parent: type T is new I as I1 and new I as I2 with null record; overriding I1 procedure Foo (X : T); overriding I2 procedure Foo (X : T); >>> I've generally materialized that as "the root of an abstraction should >>> always be declared abstract". >> >> Yes, but this is not enough, because it kills potential >> multiple-inheritance cases. > > As an implementer, knowing that multiple-inheritance is just barely possible > to implement, I'm unwilling to consider that unless no other possibility > exists. And some other way always exists. :-) But Ada 2005 did it, so I am happily using it. (:-)) >>> 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). >> >> Reuse happens on the client's side, when you share interface-wide >> implementations. This includes helper types which refer to [access] >> I'Class. Surely you have lots of them to pass widgets around, in events, >> in handlers etc. > > Not really. The implementation has such things, but we only exposed > parameters of Root_Window_Type'Class (with a couple of exceptions). The vast > majority of routines only take a single object. If you have a On_Button_Click event handler you want to pass there only implementations from Window_Clickable_Type'Class. Not just any Root_Window_Type'Class. And there is no way to place all they subclasses into single chain of inheritance. Some of Window_Clickable_Type are also Window_File_Selector_Type and Window_DnD_Type etc. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-08 6:13 ` Dmitry A. Kazakov @ 2017-08-09 0:38 ` Randy Brukardt 2017-08-09 7:06 ` Dmitry A. Kazakov 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-09 0:38 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:ombkql$rjr$1@gioia.aioe.org... > On 2017-08-08 00:59, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > >>> ... In all contexts where both become visible must require explicit >>> name >>> resolution, e.g. by renaming one of the types and/or primitive >>> operations. >> >> Ada doesn't have type renaming, so this is not possible in general. > > Not exactly renaming, but a schema to qualify the parent: > > type T is new I as I1 and new I as I2 with null record; > overriding I1 procedure Foo (X : T); > overriding I2 procedure Foo (X : T); This sort of thing is *precisely* what we mean when we talk about "type renaming". Renaming has to bring along the primitives. Sadly, we've never been able to work out a version that isn't evil (the effect of the simple version is as nasty as a package use clause, and less obvious, so it tends not to fly). >>>> I've generally materialized that as "the root of an abstraction should >>>> always be declared abstract". >>> >>> Yes, but this is not enough, because it kills potential >>> multiple-inheritance cases. >> >> As an implementer, knowing that multiple-inheritance is just barely >> possible >> to implement, I'm unwilling to consider that unless no other possibility >> exists. And some other way always exists. :-) > > But Ada 2005 did it, so I am happily using it. (:-)) Well, I only use the parts of Ada implemented in Janus/Ada, and interfaces aren't there. (Indeed, the majority of Ada 2005 isn't there, I've kinda skipped ahead to Ada 2012 which is more interesting and implementable.) >>>> 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). >>> >>> Reuse happens on the client's side, when you share interface-wide >>> implementations. This includes helper types which refer to [access] >>> I'Class. Surely you have lots of them to pass widgets around, in events, >>> in handlers etc. >> >> Not really. The implementation has such things, but we only exposed >> parameters of Root_Window_Type'Class (with a couple of exceptions). The >> vast >> majority of routines only take a single object. > > If you have a On_Button_Click event handler you want to pass there only > implementations from Window_Clickable_Type'Class. Not just any > Root_Window_Type'Class. And there is no way to place all they subclasses > into single chain of inheritance. Some of Window_Clickable_Type are also > Window_File_Selector_Type and Window_DnD_Type etc. We didn't bother. My recollection is that Windows doesn't make a distinction anyway, I believe all Windows "windows" can be clicked, just some have default actions in that case, and others do nothing. So you can use the handler on any item that has focus, and if you wanted to do something when someone clicked a text label, you could. That allows building new kinds of controls out of existing ones, among other things. In the long run, it because fairly obvious that the best design was to make everything primitive and never use class-wide items anywhere (and only use dispatching in call-backs). Places where we didn't do that we often lived to regret and in extreme cases, change (like the Move Window routine, which started out class-wide and ended up both -- as we couldn't remove the class-wide routine for compatibility reasons). Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-09 0:38 ` Randy Brukardt @ 2017-08-09 7:06 ` Dmitry A. Kazakov 2017-08-09 23:03 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-09 7:06 UTC (permalink / raw) On 2017-08-09 02:38, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > We didn't bother. My recollection is that Windows doesn't make a distinction > anyway, I believe all Windows "windows" can be clicked, just some have > default actions in that case, and others do nothing. So you basically drop typing. I don't. There are lots of languages going this path. Why use Ada? > In the long run, it because fairly obvious that the best design was to make > everything primitive and never use class-wide items anywhere (and only use > dispatching in call-backs). Huh, without multiple dispatch this has no chance to work. Anyway multiple dispatch does not supersede multiple inheritance. > Places where we didn't do that we often lived to > regret and in extreme cases, change (like the Move Window routine, which > started out class-wide and ended up both -- as we couldn't remove the > class-wide routine for compatibility reasons). I agree that there are difficult choices between class-wide and primitive. If you make everything primitive you may be hit by re-dispatch issues later. However this is more related to alternative decomposition methods Ada does not have, e.g. operation extension, delegation etc. Nothing of this can ever eliminate interfaces. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-09 7:06 ` Dmitry A. Kazakov @ 2017-08-09 23:03 ` Randy Brukardt 2017-08-10 7:13 ` Dmitry A. Kazakov 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-09 23:03 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:omeca9$11pb$1@gioia.aioe.org... > On 2017-08-09 02:38, Randy Brukardt wrote: >> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > >> We didn't bother. My recollection is that Windows doesn't make a >> distinction >> anyway, I believe all Windows "windows" can be clicked, just some have >> default actions in that case, and others do nothing. > > So you basically drop typing. I don't. There are lots of languages going > this path. Why use Ada? We were binding Windows (specifically Win32), not creating some abstract GUI. Trying to impose typing on an underlying design (especially one as complex as Win32) that doesn't have it is almost always a losing game. The goal of Claw was to allow anything that Win32 would allow, just in a higher-level manner. Moreover, allowing all of the messages to be delivered to every Window, besides being necessary if Claw could be used on window types that it wasn't aware of, also allows creating interesting new types of windows from low-level operations. The Claw Builder uses this extensively in supporting its editing mode (which relies heavily on overlays over otherwise normal windows). Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-09 23:03 ` Randy Brukardt @ 2017-08-10 7:13 ` Dmitry A. Kazakov 2017-08-11 0:33 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-10 7:13 UTC (permalink / raw) On 2017-08-10 01:03, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:omeca9$11pb$1@gioia.aioe.org... >> On 2017-08-09 02:38, Randy Brukardt wrote: >>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message >> >>> We didn't bother. My recollection is that Windows doesn't make a distinction >>> anyway, I believe all Windows "windows" can be clicked, just some have >>> default actions in that case, and others do nothing. >> >> So you basically drop typing. I don't. There are lots of languages going >> this path. Why use Ada? > > We were binding Windows (specifically Win32), not creating some abstract > GUI. Trying to impose typing on an underlying design (especially one as > complex as Win32) that doesn't have it is almost always a losing game. I am not a fan of MFC, yet they tried that. But basically you confirmed my point, it is either interfaces or low-level and weakly-typed. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-10 7:13 ` Dmitry A. Kazakov @ 2017-08-11 0:33 ` Randy Brukardt 2017-08-11 6:55 ` Dmitry A. Kazakov 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-11 0:33 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:omh11u$1bto$1@gioia.aioe.org... > On 2017-08-10 01:03, Randy Brukardt wrote: ... >> We were binding Windows (specifically Win32), not creating some abstract >> GUI. Trying to impose typing on an underlying design (especially one as >> complex as Win32) that doesn't have it is almost always a losing game. > > I am not a fan of MFC, yet they tried that. But basically you confirmed my > point, it is either interfaces or low-level and weakly-typed. I don't think they tried it much, there are only a handful of basic callbacks in Win32, and those are presented to all window types. They may have had more synthesized callbacks than we do, but we do have some. They just belong to a single branch of types and are directly implemented by the root type of the branch. (Yes, if some child type overrides the general routine and failed to call the parent routine, the whole thing will fall over in a heap. Not much to do about that in Ada 95.) There just are a number of these derived actions that are commonly used enough that we put them at the top level. That prevents the overriding problem (no one can override the message dispatching loop itself). It doesn't make sense to define, say, When_Horizontal_Scroll, on ten different window types. (Note that using interfaces, you'd *still* have to define the default implementation on all of those window types, and even with multiple inheritance that Ada doesn't have, you'd still have to override the general message routine for each of those window types [multiple inheritance can't combine the differing implementation inherited from different ancestors, that has to be done manually]. So, I don't see that interfaces or even multiple inheritance really buys much here. Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-11 0:33 ` Randy Brukardt @ 2017-08-11 6:55 ` Dmitry A. Kazakov 2017-08-11 20:49 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Dmitry A. Kazakov @ 2017-08-11 6:55 UTC (permalink / raw) On 2017-08-11 02:33, Randy Brukardt wrote: > "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message > news:omh11u$1bto$1@gioia.aioe.org... >> On 2017-08-10 01:03, Randy Brukardt wrote: > ... >>> We were binding Windows (specifically Win32), not creating some abstract >>> GUI. Trying to impose typing on an underlying design (especially one as >>> complex as Win32) that doesn't have it is almost always a losing game. >> >> I am not a fan of MFC, yet they tried that. But basically you confirmed my >> point, it is either interfaces or low-level and weakly-typed. > > I don't think they tried it much, there are only a handful of basic > callbacks in Win32, and those are presented to all window types. They may > have had more synthesized callbacks than we do, but we do have some. They > just belong to a single branch of types and are directly implemented by the > root type of the branch. (Yes, if some child type overrides the general > routine and failed to call the parent routine, the whole thing will fall > over in a heap. Not much to do about that in Ada 95.) > > There just are a number of these derived actions that are commonly used > enough that we put them at the top level. That prevents the overriding > problem (no one can override the message dispatching loop itself). It > doesn't make sense to define, say, When_Horizontal_Scroll, on ten different > window types. (Note that using interfaces, you'd *still* have to define the > default implementation on all of those window types, and even with multiple > inheritance that Ada doesn't have, you'd still have to override the general > message routine for each of those window types [multiple inheritance can't > combine the differing implementation inherited from different ancestors, > that has to be done manually]. It could provide hook within the loop. And you would have to call parent's part from the override. This is the case of overriding by an extension. > So, I don't see that interfaces or even multiple inheritance really buys > much here. It adds type safety. It a quite frequent error in GUI design to write a handler for an event that never comes. Then it allows typed arguments in the event handler. In Windows everything is LPARAM, same in Gtk. When using GtkAda it makes a huge difference. GtkAda defines some typed handlers, but not all. When you get hit by necessity to extract marshaled signal arguments and convert them to the designated types manually you thank GtkAda for all cases when you don't have to. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-11 6:55 ` Dmitry A. Kazakov @ 2017-08-11 20:49 ` Randy Brukardt 0 siblings, 0 replies; 20+ messages in thread From: Randy Brukardt @ 2017-08-11 20:49 UTC (permalink / raw) "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message news:omjkds$1lob$1@gioia.aioe.org... > On 2017-08-11 02:33, Randy Brukardt wrote: ... >> So, I don't see that interfaces or even multiple inheritance really buys >> much here. > > It adds type safety. It a quite frequent error in GUI design to write a > handler for an event that never comes. That hasn't happened to me much, probably because the specific handlers are typed (most of the handlers I've needed are edit restrictions or handling buttons). Besides, constructing this sort of code is too tedious. I generally use the Claw Builder to make the outline of the code (which includes the handlers) and manually fill in the details. > Then it allows typed arguments in the event handler. In Windows everything > is LPARAM, same in Gtk. Yes, but that is only true in the general handler; all of the specific handlers are properly typed. Hopefully, no one will actually have to use the general handler - it's there just in case something Claw doesn't consider needs to be done. > When using GtkAda it makes a huge difference. GtkAda defines some typed > handlers, but not all. When you get hit by necessity to extract marshaled > signal arguments and convert them to the designated types manually you > thank GtkAda for all cases when you don't have to. Right. Sounds like using Claw. Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-03 4:46 ` Randy Brukardt 2017-08-03 7:26 ` Dmitry A. Kazakov @ 2017-08-03 17:27 ` Eryndlia Mavourneen 2017-08-05 0:09 ` Randy Brukardt 1 sibling, 1 reply; 20+ messages in thread From: Eryndlia Mavourneen @ 2017-08-03 17:27 UTC (permalink / raw) On Wednesday, August 2, 2017 at 11:46:56 PM UTC-5, Randy Brukardt wrote: > > 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. > > 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 use task interfaces in the case in which I have a basic task design that has certain core functionality and additionally may have any of a variety of other functionalities, too. At the point at which I am ready to consolidate the interfaces into a specific kind of task, combining the interfaces, which already have declared the necessary entries (as procedures), becomes akin to building using Legos. I find this kind of construction most pleasurable to design and implement. It also is easy to understand. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-03 17:27 ` Eryndlia Mavourneen @ 2017-08-05 0:09 ` Randy Brukardt 2017-08-05 19:02 ` Eryndlia Mavourneen 0 siblings, 1 reply; 20+ messages in thread From: Randy Brukardt @ 2017-08-05 0:09 UTC (permalink / raw) "Eryndlia Mavourneen" <eryndlia@gmail.com> wrote in message news:f647e80e-7171-47be-83f2-f68eb68cb2f2@googlegroups.com... On Wednesday, August 2, 2017 at 11:46:56 PM UTC-5, Randy Brukardt wrote: ... > 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 use task interfaces in the case in which I have a basic task design that >has >certain core functionality and additionally may have any of a variety of >other >functionalities, too. At the point at which I am ready to consolidate the >interfaces into a specific kind of task, combining the interfaces, which >already >have declared the necessary entries (as procedures), becomes akin to >building >using Legos. This is the sort of thing that doesn't make a lot of sense to me. Interfaces are only useful if there are going to be multiple implementations of them. Otherwise, they just add unspeakable runtime overhead and you're getting nothing for them. Specifically, you have to be able to have useful routines made up of only dispatching calls. When I tried that in the Claw Builder, it turned into a maintenance nightmare - any significant change required a change to every specific type. And adding a new specific type took multiple days (there being so many routines to implement). It just doesn't fit with the agile-style programming that I do. >I find this kind of construction most pleasurable to design and implement. >It also >is easy to understand. Obviously, YMMV. Just don't expect me to push for anything involving interfaces. Randy. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-05 0:09 ` Randy Brukardt @ 2017-08-05 19:02 ` Eryndlia Mavourneen 2017-08-07 22:49 ` Randy Brukardt 0 siblings, 1 reply; 20+ messages in thread From: Eryndlia Mavourneen @ 2017-08-05 19:02 UTC (permalink / raw) On Friday, August 4, 2017 at 7:09:19 PM UTC-5, Randy Brukardt wrote: > ... > Interfaces > are only useful if there are going to be multiple implementations of them. > Otherwise, they just add unspeakable runtime overhead and you're getting > nothing for them. Specifically, you have to be able to have useful routines > made up of only dispatching calls. When I tried that in the Claw Builder, it > turned into a maintenance nightmare - any significant change required a > change to every specific type. And adding a new specific type took multiple > days (there being so many routines to implement). It just doesn't fit with > the agile-style programming that I do. > > >I find this kind of construction most pleasurable to design and implement. > >It also > >is easy to understand. > > Obviously, YMMV. Just don't expect me to push for anything involving > interfaces. > > Randy. The whole idea is to have "multiple implementations" of the core task, tacking on whatever additional functions may be desired to result in different tasks but with some shared functionality. I'm not an Ada language designer, but my understanding is that the piecing together of tasks in this way is handled largely by the compiler and does not *necessarily* involve dispatching: type Base_Task is task interface; procedure Awaken (...) is abstract; type Random_Things is task interface; procedure Do_Random_Things is abstract; type Persistent is task interface and Base_Task; procedure Do_Something (...) is abstract; type Temp is task interface and Base_Task; procedure Do_Something_Else (...) is abstract; ... task type Persistent_Task (...) is new Common and Persistent with entry Awaken (...); entry Do_Random_Things; entry Do_Something (...); end Persistent_Task; ... This code is "off-the-cuff" and so may be a little off, but I think the intention is clear enough. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: T'Interface attribute 2017-08-05 19:02 ` Eryndlia Mavourneen @ 2017-08-07 22:49 ` Randy Brukardt 0 siblings, 0 replies; 20+ messages in thread From: Randy Brukardt @ 2017-08-07 22:49 UTC (permalink / raw) "Eryndlia Mavourneen" <eryndlia@gmail.com> wrote in message news:74abc378-88a6-49bd-997b-fe25871b7303@googlegroups.com... ... >The whole idea is to have "multiple implementations" of the core task, >tacking on >whatever additional functions may be desired to result in different tasks >but with >some shared functionality. I'm not an Ada language designer, but my >understanding is that the piecing together of tasks in this way is handled >largely >by the compiler and does not *necessarily* involve dispatching: You're right that the specific tasks don't involve dispatching, but if the interfaces are going to have any value at all for their costs, you have to use them by themselves (typically as class-wide parameters to routines). Thus calls to those uses (parameters) them are necessarily dispatching. If you don't actually have dispatching calls, then you are generating a lot of expensive unused code in your program, and most likely bloating your application size. (Janus/Ada can trim unused primitives at link-time, but I don't think any other Ada compiler offers an optimization like that.) And it's very unclear to me what possible gain you get from using interfaces in such a case rather than just declaring the operations you need. Randy. P.S. I see a bit more value to task and protected interfaces to the normal kind, because there is no other way to get dispatching for those types. But still, it seems reasonably rare that dispatching would be useful, since you need a program with multiple tasks implementing the same interface. That doesn't happen often. ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2017-08-11 20:49 UTC | newest] Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 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 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox