From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.3 required=5.0 tests=BAYES_00, REPLYTO_WITHOUT_TO_CC autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: a07f3367d7,dbbbb21ed7f581b X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII Path: g2news1.google.com!news4.google.com!proxad.net!feeder1-2.proxad.net!feeder.erje.net!npeer.de.kpn-eurorings.net!npeer-ng0.de.kpn-eurorings.net!newsfeed.arcor.de!newsspool4.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Operation can be dispatching in only one type Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 8bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <025105f2-5571-400e-a66f-ef1c3dc9ef32@g27g2000yqn.googlegroups.com> <94e76749-c49c-45aa-b7dc-386da0d71c66@e4g2000prn.googlegroups.com> <1u0im1tdws15u.1n9v9rz7bu4t4$.dlg@40tude.net> Date: Mon, 16 Nov 2009 23:28:32 +0100 Message-ID: <39kf90ha60px$.d7746cf5cx6h.dlg@40tude.net> NNTP-Posting-Date: 16 Nov 2009 23:28:32 CET NNTP-Posting-Host: efb3c7ed.newsspool4.arcor-online.net X-Trace: DXC=9o`Z;X;DER1RLigj];iP=84IUK[6LHn;2LCV>COgUkn_?_Y?Sje\m9c@^Q34^[Hio>]I50 X-Complaints-To: usenet-abuse@arcor.de Xref: g2news1.google.com comp.lang.ada:8119 Date: 2009-11-16T23:28:32+01:00 List-Id: On Mon, 16 Nov 2009 13:35:00 -0800 (PST), Adam Beneschan wrote: > On Nov 16, 12:28�pm, "Dmitry A. Kazakov" > wrote: >> On Mon, 16 Nov 2009 09:43:06 -0800 (PST), Adam Beneschan wrote: >>> By the way, for a while I was considering requesting a language change >>> to allow this sort of restricted multiple dispatch, in cases where a >>> primitive operation of two types could be declared and inherited for >>> two derived types that are derived in the same package, and when >>> dispatching, the program would check to make sure the two actual types >>> really were declared in the same package. �This would avoid having to >>> deal with M x N combinations of types---something that I think is an >>> issue with MI---since it only deals with pairs (or triplets, etc.) of >>> types that are defined to "go together". >> >> But you still have these combinations independently on where you derive. >> You allow the "diagonal" of the full dispatching table. I.e. the >> combinations: >> >> A1, B1, >> A2, B2, >> A3, B3 >> >> But other combinations are still there, because they can be spelt. It is >> just so that they raise Constraint_Error. This "diagonal" behavior is what >> we already have for multi-methods (a form of MD with only one hierarchy >> A=B). I suppose this is one of the motivations of your proposal. >> >> But the problem with "diagonal" dispatch is that it is inconsistent with >> the idea of static typing. I would insist on the design rule that dispatch >> shall never fail in a legal program. I.e. the compiler shall enforce all >> possible combinations of types no later than at compile time. > > Since a call to a dispatching operation may have parameters that are > themselves of class-wide types, I don't think this is possible. No, what I have in mind is that each time a new type is derived, we could somehow ensure that the whole row M+1 (from N x M+1) is filled either by a overriding or per a reasonable inheritance. The major problem is that we cannot see all Ns when we do M+1. The idea of deriving both types in one package looks like an attempt to control the places where we can expand the table N x M. That is not enough to enforce completeness of the table in the above sense. There should be something more strong, but also more liberal in terms of modularization. Obviously to derive from all types related via a shared primitive operation in one package is awful (and sometimes just impossible within the given parent-child hierarchy of packages). > In Ada as it exists currently, you can declare a primitive operation > with two parameters of the same tagged type (maybe that's what you > meant by "multi-method"---sorry, I don't know the jargon). E.g. > > type T is abstract tagged null record; > procedure Some_Operation (Param_1 : T; Param_2 : T); > > If you later call > > Some_Operation (X, Y); > > and X is declared to be of type T1 (a descendant of T) and Y is > declared to be of type T2 (also a descendant of T), then the compiler > can statically determine that this will fail. But if either X or Y > (or both) is declared to be of type T'Class, then the compiler can't > statically tell whether the dispatch will fail or not. So a runtime > check is needed. Similarly for the proposal I was thinking of making. Yep, this is what I meant. The compiler should require to override *all* combinations: type T2 is new T1 with ...; overriding procedure Some_Operation (X : T2; Y : T2); -- Error! overriding procedure Some_Operation (X : T2; Y : T2); overriding procedure Some_Operation (X : T1; Y : T2); overriding procedure Some_Operation (X : T2; Y : T1); -- OK Yes, this is tedious, but the programmer should know what we does when he declares a multi-method. This is the semantics of - there are n**2 combinations which do potentially different things. If there are only n combinations, that is another case, which should *not* look MD, because it is not. I think it should somehow use tuples instead. The error should happen upon tuple construction, not in the call. For the reader it should be clear that there is only one tag. I have no idea how to spell that syntactically or by other means. Al for "true" multi-methods I think we should support delegation in order to control combinatorial explosion. For example: 1. declaration Some_Operation commutative; 2. explicit delegation of T2 x T1 to T1 x T2 overriding procedure Some_Operation (X : T2; Y : T1) renames Some_Operation with (X => Y, Y => X); 3. delegation of T1 x T2 to T2 x T2 supplying a downcast conversion from T1 to T2 overriding procedure Some_Operation (X : T1; Y : T2) renames Some_Operation with (X => (X with ...), Y => Y); 4. delegation of T2 x T2 to T1 x T2 (upcast) overriding procedure Some_Operation (X : T2; Y : T2) renames Some_Operation with (X => T1 (X), Y => Y); etc. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de