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 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!rt.uk.eu.org!aioe.org!.POSTED!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: Your wish list for Ada 202X Date: Thu, 10 Apr 2014 17:31:49 +0200 Organization: cbb software GmbH Message-ID: <17twpp4p8u7o$.1idvzaaio4f3t$.dlg@40tude.net> References: <7f1c01c5-3563-4b94-9831-152dbbf2ecdc@googlegroups.com> <8bhozh836pyt$.1qctlysud0s2q$.dlg@40tude.net> <1cdsyxjzsfgzm.1synpaujysv21$.dlg@40tude.net> <1aa804jg9qq4o$.wdiq33yo621l.dlg@40tude.net> <1w6eh0aiksmdh$.1h16p7y0b8c6h.dlg@40tude.net> Reply-To: mailbox@dmitry-kazakov.de NNTP-Posting-Host: AuYlnUSfTZrfhAkRjyySpQ.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: 40tude_Dialog/2.0.15.1 X-Notice: Filtered by postfilter v. 0.8.2 Xref: news.eternal-september.org comp.lang.ada:19221 Date: 2014-04-10T17:31:49+02:00 List-Id: On Wed, 9 Apr 2014 22:28:36 -0500, Randy Brukardt wrote: > "Dmitry A. Kazakov" wrote in message > news:1w6eh0aiksmdh$.1h16p7y0b8c6h.dlg@40tude.net... >> On Tue, 8 Apr 2014 18:37:35 -0500, Randy Brukardt wrote: >> >>> "Dmitry A. Kazakov" wrote in message >>> news:yl8s1sbhw0lw.1bhypcrvreord.dlg@40tude.net... >>>> On Mon, 7 Apr 2014 20:15:10 -0500, Randy Brukardt wrote: >>> ... >>>>> Mixed operations are not the Ada way of typing. >>>> >>>> It is Ada's way of SUBtyping. Obviously Unbounded_String and String are >>>> related subtypes, promoted to types due to implementation reasons only. >>> >>> Obvious to you only. Any single program/subsystem should stick to a single >>> string type. The fact that you can't do that in Ada (unless that type is >>> String) is the bug that needs to be fixed. >> >> I don't understand what you are trying to say. Is it that no program shall >> use both Unbounded_String and String or that there must be no String >> (Unbounded_String) at all? > > There should be no reason for a single subsystem to use more than one string > type. Where that follows from? > The fact that that is not true in Ada today is the cause of most of > the problems. This is even more perplexing. It is two different statements: 1. I can invent a string type for all purposes, thus all applications will use it. 2. Any given application needs only one string type, but different applications may require different string types. Both statements are evidently false. > As a correllary, as many operations as possible should work with all > possible string types (Root_String'Class in my formulation) -- most of the > time when you need to use multiple string types, its because you have > libraries that only work with one type (String, Unbounded_String, whatever) > and you need to use some other type. Libraries and applications use different types because each type has certain advantages and disadvantages over any other type. This is why many string types are needed, deploying different memory management strategies, different encodings and different subsets of Unicode. > So you end up converting back and > forth. If most the libraries simply take Root_String'Class, that doesn't > happen. It is as unrealistic as throwing out all numeric types and using arbitrary precision arithmetic instead. It simply does not work for real-life applications. > Ambiguous? That's the idea -- most consumers of strings don't care anything > about the properties of the string, just the sequence of code points that it > represents. Class-wide operations are overloaded, which is why. > Require type casts? No idea why you think that - that only happens in bad > abstractions where you find yourself upcasting to get at components that > "you know are there". Such things are just plain bad, and surely aren't > going to happen here as nothing of the implementation is going to be > exposed. (I.e. either use Root_String'Class, or use a specific type - and > under no circumstances should you change mid-stream.) When the result is class-wide you have to cast it to the specific type. You cannot go all the way with class-wide objects. It does not work. > >> And in any case, the whole point is to >>> eliminate the requirement to use a single, specific string type for >>> operations that should be generic (generic in the English, not Ada, >>> sense). >> >> And the whole point of keeping operation primitive is to have its >> interface generic and the implementation type-specific. > > We don't want "type-specific" implementations of most things -- that's just > adding a maintenance headache where one isn't needed. It is need for 1. safety (because you statically know that certain specific operation may not fail, while class-wide operations can) 2. efficiency There is no maintenance overhead whatsoever. Here is the proof. Let you can provide a generic implementation (as you suggested), then this implementation can be safely inherited. Therefore whether you provide an overriding or leave it as is that has no influence of the program behavior => no maintenance problem. > Why would anyone want > a "type-specific" implementation of file open? Because generic operation would not work. What lseek is supposed to do with terminal input? Files are different per nature of medium they represent, so are strings. There are interfaces common for various subsets of files and strings. But there is no single usable interface for the set of all files or the set of all strings. The model of type extension does not function in real-life. > Or exception messages? That's > precisely the cause of the problem that we currently have. The cause is that the language does not support factoring out interfaces in their variety. It either forces single interface for all objects or no common interface at all. That leads to the design of string types Ada had (no common interface). Your idea of single interface will fail as well. No interface is C programmed in Ada. Yours is SmallTalk in Ada, with any method applicable to any object and MessageNotUnderstood raised at run-time. I bet that most Ada programmers would prefer C-esque approach to that. It is uncomfortable but at least safe. > But you're saying that we shouldn't solve the problem at all, since the > entire problem is forcing the use of specific types in language-defined > libraries (and similarly in user-defined libraries). Making operations primitive does not force user-defined libraries to anything. They still can be designed in generic terms. But since there will more classes than single root string, it will be also possible to design specialized libraries as well. And I see a general language problem in inability to add primitive operations without huge efforts, e.g. type My_Type_With_New_Ops is new Old_Type with null record; There must be better means for that especially due to MD. MD will not work when involved types are frozen. > You seem so focused on virtually useless operations like Append -- they have > no real value in an Ada application, as the primitives (slicing and &) do > the job better anyway. One is forced to use them for unbounded string, > mainly because you don't have very good access to the primitives for those > types -- that's the whole idea of this change. Append is very useful because Unbounded_Strings are usually constructed incrementally by adding pieces. But that is beside the point. I am focused on the language features which would allow the programmer to describe conglomerates of types like string types. String types is just an example to illustrate language weaknesses. Same applies to numeric types, to matrices, to containers/indices/iterators. Wherever you look you see the same problem, the language type system is deficient. >>>> It does not make any sense to me. Consider the operation Append. Which >>>> class does it belong to? Does it act on String? Is the argument UCS-2? >>> >>> Append takes two operands of Root_String'Class, and returns an >>> Root_String'Class with the type of its first argument. What's the >>> problem? >> >> Append is a procedure. Modifiers of Unbounded_String are in-place >> operations, that is the major use case for having Unbounded_String at all. > > OK, then it takes an in out parameter of Root_String'Class, and an in > parameter of Root_String'Class. What's the problem? The problem is passing String as the in out parameter there. You have a behavior change undetected at compile time. This is not Ada. >>>>> No, I'm deriving from an abstract type with no representation. There's >>>>> a huge difference. >>>> >>>> No difference whatsoever. We are talking about interfaces. The interface >>>> of Unbounded_String is not the interface of String. >>> >>> That's true, but that's a bug. They *should* be the same; only the >>> runtime behavior should differ (when exceptions are raised and the like). >> >> They should not and cannot. The type String cannot have procedure Append >> because String size is contracted to be constant. Immutable bounds is the >> major use case of String. Mutable bounds is of Unbounded_String. You >> cannot have both "same." > > Of course you can. Consider Bounded string, which has a bound, but it's > partly mutable. Or better, consider the containers -- they have bounded and > unbounded versions. Semantically, they all have bounds, it's just that the > unbounded version increases the bound automatically when needed. There would > be no problem having a fixed size container (other than such a thing would > be redunant with the existing arrays). Append is defined in > Ada.Strings.Fixed, after all, so of course it works for a fixed length > string. Where? >> Everything should work exactly so it does now, but without explicit type >> conversions. > > Yeah, and every girl should want to go out with you, without an explicit > invitation. :-) Yes! That would be even better than MD! (:-)) >>>> Append (S, SUNDANESE_LETTER_KHA); >>> >>> Yes, that's good. If the underlying type cannot store the letter, >>> Constraint_Error is raised. >> >> Yes! You want weak typing all the way! > > Yes, that's exactly the idea of class-wide operations -- one weakens the > typing (by allowing classes of operations) in order to get more generality. It is not generality it is a bug. If String cannot implement this interface. Why should it pretend to have? >> In my system the above will be compile error because >> >> 1. String does not have Append; > > String *does* have Append (in Ada.Strings.Fixed). Why do you think those > operations are part of Unbounded_String but not part of String simply > because someone stuck the latter ones in a library? A.4.3 does not declare Append. declare S : String (1..10); begin Append (S, "A"); -- What is this supposed to do? > If the clients become illegal, then you don't have Beaujolias, and all is > well. But that's not the system you described. You descibed one with > preference rules, and when those exist, an addition or deletion potentially > causes one legal program to become a different legal program - because the > preference rule causes a different routine to be called rather than making > the call illegal. I never said that preference rules should have this effect. Why should they, an example? >>> That means that there is no hope for >>> reusable software - the originator of the software has to be able to >>> modify it in order to improve or correct it. If that breaks all clients, then >>> either one can do nothing at all, or people just have to stick to their >>> existing (buggy) versions. Neither is acceptable. >> >> Ada has no support for dynamic linking anyway, so it is how it is right >> now. Introducing MD won't make bad any worse. > > MD isn't the problem; preference rules are the problem. That requires a proof which shows that no set of rules can exist that fulfills the requirements X, Y, Z. So far it is word against word. Not even X, Y, Z is formulated. > And what does dynamic linking have to do with anything? You should be able > to get the new version of GTK or Claw and recompile -- if legal, the program > should work the same way. Period. That's not the case in a system with > preference rules for user-defined operations. I see no problem why it shouldn't be possible. As for dynamic linking, the point is to use a new version *without* recompiling and re-linking. >>> But it's all we have. Sure, you can map a tag (this requires a loop, either >>> a brute force lookup or some fancier but much more code-intensive version), >>> but that's going to make dispatching far more expensive. You can't do this >>> mapping at compile-time because what mapping you need depends on the >>> interfaces in use. >> >> I can build a perfect hash at bind/link time when all involved tags become >> known. > > "can" means "possible", not "practical". That might be possible if the > number of tags is small, but that's not the case in a lot of OO systems. (A > Claw program starts with somewhere around 80.) Finding a perfect hash gets > very time consuming if the number of items is large - I don't think people > will be very happy with binding that takes 12 hours. A suboptimal hash wont make much harm. You use different algorithms for debug and release version optimized for speed. I don't see it as a problem. -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de