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=-1.9 required=5.0 tests=BAYES_00 autolearn=ham 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!postnews.google.com!13g2000prl.googlegroups.com!not-for-mail From: Adam Beneschan Newsgroups: comp.lang.ada Subject: Re: Operation can be dispatching in only one type Date: Tue, 17 Nov 2009 14:10:54 -0800 (PST) Organization: http://groups.google.com Message-ID: <691d6892-bc5e-4d81-8025-c36556bf2593@13g2000prl.googlegroups.com> 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> NNTP-Posting-Host: 66.126.103.122 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1258495854 1934 127.0.0.1 (17 Nov 2009 22:10:54 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Tue, 17 Nov 2009 22:10:54 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: 13g2000prl.googlegroups.com; posting-host=66.126.103.122; posting-account=duW0ogkAAABjRdnxgLGXDfna0Gc6XqmQ User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618),gzip(gfe),gzip(gfe) Xref: g2news1.google.com comp.lang.ada:8134 Date: 2009-11-17T14:10:54-08:00 List-Id: On Nov 16, 2:28=A0pm, "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 enoug= h > 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 impossibl= e > within the given parent-child hierarchy of packages). .... > Yep, this is what I meant. The compiler should require to override *all* > combinations: > > =A0 =A0type T2 is new T1 with ...; > =A0 =A0overriding > =A0 =A0 =A0 procedure Some_Operation (X : T2; Y : T2); > =A0 =A0 =A0 =A0 -- Error! > > =A0 =A0overriding > =A0 =A0 =A0 procedure Some_Operation (X : T2; Y : T2); > =A0 =A0overriding > =A0 =A0 =A0 procedure Some_Operation (X : T1; Y : T2); > =A0 =A0overriding > =A0 =A0 =A0 procedure Some_Operation (X : T2; Y : T1); > =A0 =A0 =A0 =A0 =A0-- 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 i= t > 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. 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. 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.) 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. 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. 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. -- Adam