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!news3.google.com!feeder3.cambriumusenet.nl!feed.tweaknews.nl!217.73.144.44.MISMATCH!feeder.ecngs.de!ecngs!feeder2.ecngs.de!194.25.134.126.MISMATCH!newsfeed01.sul.t-online.de!t-online.de!newsfeed.arcor.de!newsspool3.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> <39kf90ha60px$.d7746cf5cx6h.dlg@40tude.net> <691d6892-bc5e-4d81-8025-c36556bf2593@13g2000prl.googlegroups.com> Date: Wed, 18 Nov 2009 10:46:59 +0100 Message-ID: <1h9hilcg5i6il.12edpgu4szw1h.dlg@40tude.net> NNTP-Posting-Date: 18 Nov 2009 10:47:00 CET NNTP-Posting-Host: c50d4100.newsspool2.arcor-online.net X-Trace: DXC=B1ll]R=RmU?QbA1[CgMQ00A9EHlD;3Yc24Fo<]lROoR18kF7enW;^6ZC`4IXm65S@:3>?h@aU\7ohYk8 X-Complaints-To: usenet-abuse@arcor.de Xref: g2news1.google.com comp.lang.ada:8139 Date: 2009-11-18T10:47:00+01:00 List-Id: On Tue, 17 Nov 2009 14:10:54 -0800 (PST), Adam Beneschan wrote: > On Nov 16, 2:28�pm, "Dmitry A. Kazakov" > wrote: > >> 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). > > .... > >> 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. > > It appears to me that we're talking at cross-purposes. No, it is the same problem of MD. It has some special cases like multi-methods, which are simpler, but it is still MD. The example you provided is full MD. You have three hierarchies: Document'Class, Text_Region'Class, Marker'Class An operation can be primitive in any combinations of types from these hierarchies. > I was trying to solve one particular class of problems; > you seem to be trying to solve the entire Multiple > Dispatch problem. I believe that when I first thought > about making this proposal, I was assuming that a fully > general multiple dispatch wasn't ever going to be part > of the language, so I was thinking about an improvement > for one particular case I had run into. > > Here's an example of the sort of problem I'm thinking > about: Suppose you want to define an abstract type that > represents a document, which could be a plain ASCII > text file, a Word document, a PDF file, etc., that all > have in common that they consist of sequences of > "characters" and "other elements of some sort". Some > of the documents may also have formatting information > or other good stuff, but these won't be common to all > documents. > > You want to write a package that deals with documents > and particularly with the text (characters) in the > documents. The type of document (plain text, Word, > etc.) won't be known until run time. Some of the > operations you want to provide are: search for given > text in the document, and return "markers" that point > to the beginning and end of the text that is found; and > move text from one point to another in the document. > > A natural way to do this, it seems, would be to define > a Document as an abstract type, and let other packages > (Plaintext_Documents, Word_Documents, PDF_Documents, > etc.) define concrete types as extensions of that type > for plain text, Word documents, PDF documents, and so > on. You also want to define, say, a Text_Region type > that represents a region of text in a document, and a > Marker type that represents a particular point in the > document text, between two characters. The Text_Region > and Marker types should be abstract also, since we > don't know how they'd be implemented for different > document types; for a plain text document, a Marker is > probably just a string index, in essence, but the > Word_Documents and PDF_Documents might unpack a file > into some complex internal data structure when it reads > it, so a Marker for those document types might contain > pointers into the internal data structure, or > something. > > So it seems natural to write the package like this > (along with other operations): > > package Documents is > > type Document is abstract tagged private; > type Text_Region is abstract tagged private; > type Marker is abstract tagged private; > > function Search_For_Text (Doc : Document; Text : String) > return Text_Region is abstract; > -- I'm assuming here that it would return some sort of > -- "no region" value if the text is not found > function Beginning_Of (Reg : Text_Region) return Marker > is abstract; > function End_Of (Reg : Text_Region) return Marker > is abstract; > > procedure Move_Text (Doc : in out Document; > From : in Text_Region; > To : in Marker) > is abstract; > > end Documents; > > The last would cut the text represented by the From > region and move it to the point specified by "To". (It > would be up to the packages to figure out how to move > formatting information or other information in an > appropriate way.) > > Of course, Move_Text can't be declared because it is a > primitive operation of more than one tagged type. > Actually, none of the functions can be declared, > either, but I want to focus on the Move_Text procedure. > You might want to call Move_Text with a > Word_Documents.Document, Word_Documents.Text_Region, > and Word_Documents.Marker, or similarly with three > objects all with types from the PDF_Documents or > Plaintext_Documents package, but you would never want > to mix objects from two different packages. As an example consider these operations: procedure Cut ( Doc : in out Document; From : in Text_Region; Clipboard : in out Document ); procedure Paste ( Clipboard : in Document; Doc : in out Document; To : in Marker ); > And that > was the purpose of the proposal I was thinking of > making: to allow for restricted use of multiple > dispatch for cases like this (and this is a situation I > believe I've run into more than once), in which > Move_Text could be declared but could only be called if > the parameters' specific types all come from the same > package, checked at runtime if necessary. The > Move_Text procedure would be inherited in each of the > other packages (Plaintext_Documents, etc.), with types > from that package, but there would not be any inherited > Move_Text that would involve types from different > packages. (This was an idea I first thought about a > long time ago, but eventually abandoned; I really > hadn't thought about how to deal with the functions.) So if you derived ASCII_Text from Plain_Text you would lose Move_Text if you forgot to derive from Text_Region and Marker? > There are workarounds, of course. As I responded to > the original poster in this thread, you can make some > of the parameters to Move_Text class-wide, and the > concrete procedures would check to make sure the actual > tags for the class-wide parameters are correct---or > just doing a type conversion will do the check: > > package body Word_Documents is > > overriding > procedure Move_Text (Doc : in out Document; > From : in Documents.Text_Region'Class; > To : in Documents.Marker'Class) is > X_From : Text_Region renames Text_Region(From); > X_To : Marker renames Marker(To); > ... > > I think that's correct. Anyway, those will raise > Constraint_Error if the parameters are from the wrong > package. (BTW, the jargon word is "covariance". Document, Text_Region and Marker are said "covariant" in Move_Text.) > However, I consider that to be a workaround (maybe > others don't think it's that bad), which is why I was > thinking about making this proposal---to make things > work more "naturally", without a workaround, in this > sort of situation that I've run into multiple times. > I'm not sure what your idea is trying to solve (other > than "making multiple dispatch perfect"); but even if > it does make general multiple dispatch available, your > way of doing things would not solve anything in this > sort of case, because you would require Move_Text to be > overridden for every possible combination of children > of the types, which makes it unusable and means that > even with your Grand Solution To Everything, those of > us who want to implement something like the above would > have to go back to using the workaround. Consider again ASCII_Text derived from Plain_Text. Let we also derived from Plain_Text_Region and Plain_Marker: Plain_Text <-- ASCII_Text Plain_Text_Region <-- ASCII_Region Plain_Marker <-- ASCII_Marker Now, my concern is what happens with Move_To called on ASCII_Text, Text_Region, Plain_Marker You say, it is Constraint_Error. The question what is the reason for this? I don't see any. It is for the programmer to decide. I you say the language forbids that, I say OK, but then that MUST be done static. Anyway your proposal would impose some draconian limitations on the packages structure. E.g. it would be impossible to provide implementations and different types of Marker in separate packages. Or consider a generic implementing a Marker for the given document type. Would that work? > That's why I think we're not on the same page---we're > trying to solve two different and unrelated problems > that seem only superficially related. Maybe we can't > solve them both. Actually I considered both cases with the requirement of the constraint being static. To summarize: 1. Full MD = no constraint => all combinations checked and required 2. SD on tuples = static constraint on the combinations The case 2 has consequences, of course. What I find totally inappropriate for a language like Ada is: 3. Dynamic constraint with run-time checks dropping arbitrary exceptions. I think we should have learnt something from the "accessibility checks disaster". -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de