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,73cb216d191f0fef X-Google-Attributes: gida07f3367d7,public,usenet X-Google-NewGroupId: yes X-Google-Language: ENGLISH,ASCII-7-bit X-Received: by 10.224.219.146 with SMTP id hu18mr3475691qab.3.1365341773124; Sun, 07 Apr 2013 06:36:13 -0700 (PDT) MIME-Version: 1.0 Path: ef9ni13605qab.0!nntp.google.com!border1.nntp.dca.giganews.com!border4.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!backlog2.nntp.ams.giganews.com!border4.nntp.ams.giganews.com!border2.nntp.ams.giganews.com!nntp.giganews.com!npeer.de.kpn-eurorings.net!npeer-ng0.de.kpn-eurorings.net!news.n-ix.net!news.bawue.net!news1.tnib.de!feed.news.tnib.de!news.tnib.de!weretis.net!feeder4.news.weretis.net!nuzba.szn.dk!news.jacob-sparre.dk!munin.jacob-sparre.dk!pnx.dk!.POSTED!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Is this expected behavior or not Date: Mon, 1 Apr 2013 19:40:42 -0500 Organization: Jacob Sparre Andersen Research & Innovation Message-ID: References: <1hvv2kd9smnfx.6spgz9thd1mh$.dlg@40tude.net> <1raubw1sk48ca$.69rdgczvnnf.dlg@40tude.net> <2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net> <1u72u7h5j4jg3$.wlxmaltyzqik.dlg@40tude.net> <1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net> NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1364863245 6843 69.95.181.76 (2 Apr 2013 00:40:45 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Tue, 2 Apr 2013 00:40:45 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.6157 X-Original-Bytes: 17292 Date: 2013-04-01T19:40:42-05:00 List-Id: "Dmitry A. Kazakov" wrote in message news:1gnmajx2fdjju.1bo28xwmzt1nr.dlg@40tude.net... .... > The point is that whether you create a totally new string hierarchy or > create one for already existing string types, you will have the issue with > "&" (and any other operation with more than one argument/result of string > type). That is *independent* on whatever Ada did or not before. It is in > the nature of a multi-method, which "&" is. If you want a hierarchy of > strings you *must* face this problem. No you don't. There are no language-defined multi-methods. String & String = String is not a multi-method. You, the user, can define such operations, of course, but then you have the deal with the consequences. Generally, it's best if you don't do that. ... >> If the container operations take parameters of type Key, then you can >> only >> pass a Position to such a parameter if you use an explicit conversion. > > Position and Key are just same type according to you. You said you don't > need independent hierarchies of any types, which should include numbers. You're not making any sense. We're talking about hierarchies of types; *everything* in such a hierarchy is a separate type. (Ada subtypes are completely independent of any type hierarchies, and completely irrelevant for this purpose.) There really is only one hierarchy of types per programming language; the only question is how much interoperation between different types is allowed. It's probably misleading to ever say that there is "more than one hierarchy of types" in a program (or programming language). My guess is that you've redefined the meaning of hierarchy again, so please just forget it, there's no point in discussing this further. If you're unwilling to use Ada terminology on this Ada list, then we really have nothing to talk about. >>> The model of Ada 95 tagged types provides a class with shared >>> representations. This need to be augmented for the case when >>> representations has to be different. Note that this was partially done >>> when >>> Java interfaces were added in Ada 2005. Java interface is a type without >>> any representation, so there is nothing to inherit from, except for a >>> slot >>> for the type tag. Drop that slot, and you will have a workable model for >>> building classes of scalar types and arrays. >> >> I don't know how one could implement "interfaces" without a tag. > > You have the tag in the representation of untagged'Class. You don't have > it > in the representation of untagged. Doesn't work, as I've previously explained. You have to be able to inherit implementation of operations, for all types. And there exist plenty of Ada types for which copying is not allowed. The only way to implement those is via some sort of dispatching, and the need poisons the possibility of omitting tags, even for "specific" operations. You can of course adopt severely incompatible rules (can't inherit operations for derived limited types) or add complexity by making a new kind of derivation (you can't get rid of the old kind, so you're adding lots of new complexity without eliminating any old complexity). Neither sound appealing to me. For a new Ada-like language, the choices are different, but for Ada itself, it doesn't really work. I've explained this several times already and I'm not bothering to do so again. >>>>> We also nd "extension" that drops parent's representation altogether. >>>>> E.g. something like: >>>>> >>>>> type Character is new Unsigned_8 -- or enumeration, whatever >>>>> and Wide_Wide_Character'Interface; ... >> You miss my point: the effect is to make *every* operation in *every* >> subprogram -- including specific ones -- dispatching -- which would be >> way >> too expensive in practice (no optimization would be possible). > > Then it is wrong what you wrote. There will be no dispatch on specific > types. > > (I don't understand why you think that dispatching on specific types is > necessary) I've explained it previously and above again. You're welcome to disagree, but the only way to *prove* me wrong is to create a real proposal, in *Ada* terms, with proposed wording using *Ada* terminology, that does not have any significant incompatibilities. You've never made any attempt to address the real problems to this point, and I'm pretty certain that you can't. ... >> You are still misunderstanding. You'd *have* to have redispatch because >> the >> only way to implement inheritance would be to make all operations (even >> those very low-level ones) dispatching in *all* instances. There could be >> no >> statically bound operations. > > Yes, I still do not understand what has re-dispatch to do with inheritance > (of what?) > > The representation is NOT inherited > > Primitive operations (AKA, interface) are inherited in the way standard to > tagged types. That is, a NEW operation is declared with the same name and > the profile where the parent type is replaced by the descendant type. > > The way its body is generated out of old body with parent type converted > to > the descendant type in- and/or out. > > How this requires re-dispatch? The type conversions are view conversions, and they never make copies. That forces the representation to be compatible. You could change that for by-copy types (although that would have run-time compatibility issues for controlled objects), but you can't change that for types that have no copy operation (like tasks and protected objects). So how to do you implement them? Array of task is an untagged type, too, and it certainly should be able to use 'Class. ... > I don't ban inheritance of the representation. I want to be able not to do > it when I don't need it, e.g. for character and string types. But it's not that easy. If you have an array of tasks: type Foo (1 .. 10) of Some_Task with Component_Size => 32; and you derive another array of tasks from it: type New_Foo is new Foo with Component_Size => 64; This is legal, and you have different representations. >> It really kills the entire idea. > > No, IF String inherited the representation of Wide_Wide_String, THAT would > kill the idea. > > The whole idea is not to inherit irrelevant representations! I don't see the problem here; if Root_String is an abstract tagged type, the various concrete types derived from it all have completely diifferent representations. It's the same as happens for controlled types: there is no requirement that the representation of different controlled types is the same. This is standard stuff - if you don't want to inherit a representation, then don't, inherit from an abstract type (or interface, if you prefer) that has no representation. Don't try to get rid of an already existing representation, because that makes real trouble for inherited operations. ... > The bottom line is, I regard Ada 83 construct "type S is new T;" as very > useful, and wished it be valid with all specific types without silly > exceptions Ada 95 made for tagged types. Fair enough. I regard "type S is new T;" as a junk piece of syntax that was inherited from Ada 83, and should never be used. We completely disagree on this one, and there really is nothing worth talking about. You previously asked about: type Velocity is new Float; That would get you a repremand if you worked for me. You never, ever use the types in Standard (because they're not necessarily portable to other compilers). You derive types based on your actual application requirements: type Velocity is digits 5 range -1.0E+10 .. 1.0E+10; And let the compiler pick the representation. Similarly, if you are matching hardware, you declare types that match that hardware (specify Size, Object_Size, etc.). If you're writing true throw-away code, just use the types in Standard directly and forget the strong typing (it's throw-away, after all). There are so few cases that don't fit in one of these that it doesn't pay to have the feature in the language. Especially if we can fix the "renaming of the contents of an instantiation" problem somehow. ... >> The only way I know of to implement multiple inheritance is with >> a linked-list of tags, which isn't too bad when only a few interfaces are >> involved. But once you get the dozens you're talking about, it's going to >> cause a very significant overhead. > > There is no overhead on any existing Ada program. Only if the compiler-writer can implement many special cases in their code. I think this is unlikely; perhaps AdaCore has the resources to pull it off, but I doubt that any other vendor does. Janus/Ada tends to implement all types with the same code and optimize to better code, meaning the most general case is the typically the only thing that we implement. It wouldn't be possible to optimize that to anything remotely like the existing Ada code, certainly not with the resources we have. And we'd be going backwards at best - no thanks. ... >> Because you need operations that work on every object, >> copyable or not. Remember, there are no type conversions between types in >> different hierarchies. > > And, this is what different hierarchies are for. For what? To make it impossible to pass integers to Text_IO, or to use them to instantiation Text_IO? (If you can't convert, you can't instantiate or use 'Class either.) How is that going to help make Ada more regular?? ... > And cloning is there to enforce checking. Huh? You get checking every time you make a new type, whether it is in the same hierarchy or a different one. The hierarchy defines what conversions are allowed (to/from 'Class, between related types). That's it. The type checking for specific types is exactly the same either way. ... >>> But they are still the same >>> hierarchy. You need some fundamental operation which tells that a type >>> breaks off the hierarchy. >> >> Yes, of course all containers ought to be members of the same hierarchy. >> How >> else would you create generic algorithms? > > Easily. Cloning borrows all operations. Define algorithm on the original > type. Then clone it. Done! But you have cloned nothing. Either you have a conversion to the original type, in which case they belong to the same hierarchy. Or you don't have a conversion, and then you can't inherit any implementations, because that involves conversions. >>>> As soon as user-defined things are involved, preference rules simply >>>> don't work. >>> >>> Some rules are clearly needed to choose between: >>> >>> function "&" (Left : String; Right : Wide_String) return Wide_String; >>> function "&" (Left : String; Right : Wide_String) return String; >> >> There are no such operations predefined in Ada, and that's because you >> *can't* chose between them. You can of course declare them yourself >> (that's >> essentially what happens in Ada.Strings.Unbounded), but the net effect is >> that you then cannot use literals with such a type. Ada does not attempt >> to >> prevent you from shooting yourself in the head. :-) > > Are you seriously going to propose a string class without "&"? A string class with a mixed & is nonsense. (I think the String & Character in Ada 83 was nonsense, but it's not a problem here.) The only & is String & String = String, and so on for all types. For compatibility, we'd also have String & Element = String. Nothing else -- no mixed string types. You never need such types anyway, they just make understanding of an expression impossible. >>> My take on this that the language should prevent situations when you >>> have >>> an object with some of its operations invisible, especially, when these >>> operations override the same primitive operation. I think this should be >>> possible to do while keeping it backward compatible, because standard >>> types are always visible anyway. >> >> Huh? This is very common with private types. With interfaces, we enforced >> such a rule and it is rather limiting. >> >> Claw uses hidden operations on window objects to keep the mechanisms of >> the >> message loop hidden away. > > I didn't meant that. Whether public or private an operation on the object > should be visible if you would see it otherwise, e.g. through use-clause. I think that's already the case. The problem is with "additional operations" that appear when you know more about a type, and that's completely related to private types and nesting. In my Ada-like language, I would ban that from happening, but it's 30 years too late for Ada in this way. ... >> You can do this sort of thing in exceedingly simple cases. But it simply >> gets too complex the more properties that you try to decompose on. And >> every >> such property is making all of your dispatching calls slower and slower. > > I would gladly buy that in exchange for how it is now: 100+ generic > packages, 1000+ instances, 4 hours compilation time, no way to compile on > a > 32-bit host. Fair enough; the problem is that you're in a very small minority. I know I would not accept that kind of slow-down in my code, especially if there was no corresponding benefit for me. >> Moreover, most interesting properties are not binary like the file mode. >> They tend to depend on the *values* of parameters, and often on >> combinations >> of values. It just is too complex to do. > > It is becomes increasingly expensive not to do it. There is a language > damage as well inflicted by all hacks of Ada 2005-2012. Further hacks are > in the pipe line, I guess. No idea, we haven't done much yet, private musings by me means little. I think there would be an argument for the position that we're reaching the limit of what we can do sensibly to Ada, and that we might have to make a clean break at some point to get rid of all of the legacy garbage. But I suspect that there wouldn't be enough customers for that sort of incompatible change. (See all of the problems the Python people are having from when they did that.) >>> It is not about checking, especially because the above construct is >>> still >>> possible to get through generics. It is just a stupid limitation >>> motivated >>> by urban legends mindlessly repeated through (using you wording) >>> OO-baloney >>> texts. >> >> Implementability is hardly an "urban legend". If the resulting code is >> too >> slow to use > > I saw no significant overhead in C++ programs, which has full MI from the > start. C++ is free of some of the Ada 83 legacy that weighs us down. There's a reason that Ada never will allow redefining of ":=", for one example. (I'm also dubious of your actual assertion; you probably aren't looking in the right places. I certainly can believe that you aren't seeing that slow-down, perhaps other effects predominate. I know I would see it, but of course I can't say how significant it would be without actually benchmarking it -- which isn't going to happen because I'm surely not implementing you're imaginative language.) Randy.