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: 103376,dbcfe2b0a74da57e X-Google-Attributes: gid103376,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news2.google.com!news4.google.com!feeder1-2.proxad.net!proxad.net!feeder2-2.proxad.net!newsfeed.arcor.de!newsspool4.arcor-online.net!news.arcor.de.POSTED!not-for-mail From: "Dmitry A. Kazakov" Subject: Re: Inherited Methods and such Newsgroups: comp.lang.ada User-Agent: 40tude_Dialog/2.0.15.1 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Reply-To: mailbox@dmitry-kazakov.de Organization: cbb software GmbH References: <1190239986.762473.204290@k79g2000hse.googlegroups.com> <1rw45b3rmvmcr$.1df4wst5oknbl$.dlg@40tude.net> <1190296353.624737.150940@y42g2000hsy.googlegroups.com> <11m13st1f92kf$.m8s6y8mc8ebk.dlg@40tude.net> <1190321119.206313.65290@57g2000hsv.googlegroups.com> <1190408526.100291.265040@50g2000hsm.googlegroups.com> <9ukf2wtqjs0q$.iuijmal4x56b$.dlg@40tude.net> <1190497995.498679.119190@19g2000hsx.googlegroups.com> <1mw3qju08q8uj.sgzht7ld9ydc$.dlg@40tude.net> <1190579805.451187.71140@d55g2000hsg.googlegroups.com> <1i8ksr774bjbj.vpmnx3c0i9qz.dlg@40tude.net> <1190646125.024072.310020@19g2000hsx.googlegroups.com> <1r9s9v6pcjifl.vp4ktk0unpd1.dlg@40tude.net> <1190753631.240548.101820@19g2000hsx.googlegroups.com> <1hlqzsdiq2hxf$.nni5xz67fc13.dlg@40tude.net> <1190842261.235691.298520@50g2000hsm.googlegroups.com> Date: Thu, 27 Sep 2007 17:02:20 +0200 Message-ID: NNTP-Posting-Date: 27 Sep 2007 16:56:42 CEST NNTP-Posting-Host: 29fe0af1.newsspool3.arcor-online.net X-Trace: DXC=K\YJmlm[REL430`Ic\XY[6LHn;2LCV^7enW;^6ZC`TIXm65S@:3>_>@`Z6DASe5Y X-Complaints-To: usenet-abuse@arcor.de Xref: g2news2.google.com comp.lang.ada:2161 Date: 2007-09-27T16:56:42+02:00 List-Id: On Wed, 26 Sep 2007 14:31:01 -0700, Maciej Sobczak wrote: > On 26 Wrz, 12:42, "Dmitry A. Kazakov" > wrote: > >> No, because the specific type does not kill primitive operations it only >> freezes them. > > Not much. I can recover T'Class from T, as in the example from > previous post. Nonetheless, T'Class /= T. Formally, you don't recover it, you create a new object, then you call some operation on the result, and after completion you convert it back. The compiler may optimize memory use. For by-reference type it could be required to do so. > How is it possible to recover T'Class from T? Because T inherits class-wide operations of T'Class. > Apparently the type I see in Initialize is somehow decoupled from the > type of the object itself. In other words, what I see in Initialize is > not the whole "truth" about the object. > The truth is within the object > itself, not in the parameter of Initialize, and with appropriate > question I can get the full answer. > But this only means that T does not really fully determine X. It does. It has a primitive operation that constructs T'Class from T. For a tagged type this operation uses the tag embedded in the representation of T. This fully determines the outcome both in Ada and C++. > With appropriate application of the notion of view this is easy - as > far as I'm concerned, the object is T'Class, but Initialize sees only > the T view on it. If Initialize were a constructor hook on T, then the language should classify the program using the conversion operation above as erroneous. In my view to avoid inconsistencies, the conversion T -> T'Class should yield an object with the tag = T, no matter what the object was before, otherwise it shall fail. The object's history is erased after dispatch, now it is T, no matter what the embedded tag tells. For tagged types, Constraint_Error should propagate when the tag differ from T. Note an important difference to C++, C++ does this only upon construction/destruction. I think that this should be done always. I think we have discussed it before. I'll try to explain it on a different model: Consider a specific type as a point T. Then a class were an open interval [T, oo[. The types algebra is built on points and open intervals. Subprograms are defined on either points or intervals. So far, so good. Now, what you want is to get in the constructor of some S derived from T, something like a *closed* interval: [T, S]. But you don't have operations in the types algebra for dealing with such beasts. And the subroutines aren't defined on them. This is inconsistent with the setup above. Additionally to specific, polymorphic operations it would require "finite" operations. They should be allowed outside the constructors, i.e. they would leak out in the language for the sake of regularity. It will be complex. > But you claimed that views are not needed. Try to explain this without > reinventing views. :-) See above. N.B. Certainly, you could play with a model where each polymorphic object were a triple: (View_Type, Native_Type, Native_Value). Then you could try to figure out the meaning of: operation Foo of S called on T as if it were U. Good luck! IMO there is enough problems with a much simpler model. >> The >> result of this conversion would be wrong if Initialize were a hook on the >> constructor of T. But it isn't. So formally everything is OK. Initialize is >> a hook on the constructor of T'Class which is officially constructed, no >> matter that S's Initialize wasn't called. > > None of Initializes was called before T'Class was complete. That's the > problem. It's entirely reversed, leading to untyped mess. *If* Initialize were a constructor. >> Note that the case you presented is just a variant of the more general >> problem called "re-dispatch." As your example nicely illustrates, >> re-dispatch is inherently inconsistent. > > I'm not sure whether this is inherent, or just a consequence of the > fact that T'Class is formally complete before it's initialized. It is a consequence of contract violation. T is specific, you may not exploit its tag, without being punished. >>> I want to register T'Class, but I don't want to involve those who >>> derive from T. >> >> Sorry, but T'Class includes them, your design is inconsistent with that. >> Can you explain where could it be useful? > > Abstract factories perhaps? > I want to set up a framework for the abstract factory design pattern. > The base types and registry are part of the framework and the user > provides the concrete factories. The base types register the factories > in the registry so that later the user can request them and get > concrete behaviour. > This is cool and clean only if the registry mechanics is encapsulated > within the framework, so that the user does not have to care about it > in his own constructors - but this is possible only if the base type > can register T'Class, not just T. Register from the constructor of T'Class. Factory were then an abstract primitive operation of T. >>>> You could say it simpler: Children and Adult are different types. Period. >> >>> They are both in Human'Class. You try to escape the problem instead of >>> solving it. >> >> I don't see any. If they are in Human'Class <=> they have the behavior of. >> A client would use that behavior. Why do you need to change anything? > > A client can ask for the additional interface after discovering the > concrete type. It is called dispatching, no need in changing type. Dispatching does that for you. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de