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.66.242.197 with SMTP id ws5mr1985965pac.32.1364266965810; Mon, 25 Mar 2013 20:02:45 -0700 (PDT) MIME-Version: 1.0 Path: q9ni25799pba.1!nntp.google.com!npeer03.iad.highwinds-media.com!news.highwinds-media.com!feed-me.highwinds-media.com!border3.nntp.dca.giganews.com!border1.nntp.dca.giganews.com!border4.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!exi-in1.telstra.net!news.telstra.net!newsgate.cuhk.edu.hk!goblin2!goblin.stu.neva.ru!feeder.erje.net!eu.feeder.erje.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: Fri, 22 Mar 2013 21:33:02 -0500 Organization: Jacob Sparre Andersen Research & Innovation Message-ID: References: <11rcs3gg4taww$.bylek8fsshyz$.dlg@40tude.net> <99929f93-b80f-47c3-8a37-c81002733754@googlegroups.com> <87ec4b1d-f7cd-49a4-8cff-d44aeb76a1ad@googlegroups.com> <78103a2f-5d19-4378-b211-1917175d5694@googlegroups.com> <3p6p8k0yfly7.ctazdw7fc5so$.dlg@40tude.net> <1jtvzi1v65aqm.1k5ejsveno59f.dlg@40tude.net> <1hvv2kd9smnfx.6spgz9thd1mh$.dlg@40tude.net> <1raubw1sk48ca$.69rdgczvnnf.dlg@40tude.net> <2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net> NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1364005985 11907 69.95.181.76 (23 Mar 2013 02:33:05 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Sat, 23 Mar 2013 02:33:05 +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-Received-Bytes: 14883 Date: 2013-03-22T21:33:02-05:00 List-Id: "Dmitry A. Kazakov" wrote in message news:2qwq2cdeuvhu$.qtnb8zyhuob9$.dlg@40tude.net... > On Thu, 21 Mar 2013 18:27:22 -0500, Randy Brukardt wrote: > >> "Dmitry A. Kazakov" wrote in message >> news:i93qv6ba3bv0.wuicbsmfm5ha.dlg@40tude.net... >>> On Wed, 20 Mar 2013 18:57:58 -0500, Randy Brukardt wrote: >> ... >>>> Even if you are willing to confuse users with implicit dispatching, >>>> you're >>>> also talking about turning every slice reference into a loop. > >>> I don't see why. When the slice object happens to be class-wide, you >>> have >>> a dope with a tag, bounds and a reference to some yet-to-be-discovered >>> representation. When the slice is specific, you have a dope with bounds >>> and a reference to some statically known representation. >> >> The underlying model of a slice is an implicit loop. We already have to >> use >> loops to implement some slices in existing Ada; there is no possibility >> of >> eliminating that. That's because ultimately everything is done on machine >> objects (bytes, words, dwords, etc.) and you always need a loop if you >> are >> going to operate on more than one. > > I still don't understand why is it relevant. Ada already has "loops" you > are talking about for String and Wide_String. Why cannot you use them for > their representations after selecting through dispatch? You can - but there is no benefit to doing so, so why bother? >> Because of that, there is almost no value to slicing operations unless >> you >> know the representation and can use block move instructions. > > I want to be able to pass a slice to Put_Line without copying. I want to win the Powerball so I can use the money to advance Ada and programming. Doesn't mean that it's practical or possible. >> There's nothing that you can do with a slice that you can't do with a >> loop, >> and usually the loop is easier to write and understand. > > Are you suggesting to call Put from a loop instead of Put_Line? I Don't > want the language forcing me doing that. You need a loop somewhere (or a complex abstraction); I suggest it be done at the call-site because there is insufficient value to doing it elsewhere. In your particular example, that means that the slice needs to be a new object. That doesn't necessarily mean copying of the data. If the designer of the abstraction, have put in enough smarts to share representations -- after all, if Unbounded_String can do it, so can Unbounded_UTF8_String. But as with Unbounded_String, I don't think the language should get involved in this. A compiler can copy a slice of an String any time it wants in Ada today -- I see no reason to change that. (And Janus/Ada uses that to support generic sharing in some instances.) ... >> Slicing is already impossible for the case that we're talking about, > > ? > > Normal strings have slices and should continue to have them. Sure, but Root_String'Class is a separate type hierarchy. I don't think there can be any sharing between them other than through a set of defined conversions. If we go this way, new programs should avoid String and Wide_String altogether (there would be a new type rooted at Root_String that provided those representations). >> and >> interface to foreign language already has to be done through special >> types. > > Which should certainly be in the same class! There is no semantic reason > why char_array should not be considered string. It won't work, semantically or implementation-wise. This is a total restart of String semantics, and the old semantics will still exist (probably in Annex J). There is no way to make the existing array semantics work like a tagged type, and that is absolutely necessary for dispatching to work (even if it isn't a "tagged type" in Ada terms). ... >> No I mean all objects. It should be none of your business how the >> compiler >> implements objects > > On the contrary, the compiler is free to choose a representation under the > constraints specified by the programmer. I don't want Ada to become C#. That's the same thing I said, so I don't know why you are claiming that this is different. The compiler always has the power to reject things the programmer specifies if it can't implement them. (The "Recommended Level of Support" puts some minimum requires on what ought to be supported.) ... >> None of the above makes any sense whatsoever. We need all of those things >> in >> the object in order to generate code. > > So, you want to describe all possible problem domains in the RM? The RM > should know that a matrix of 2 rows and 5 columns can be multiplied to a > 5x8 matrix, but not to a 8x8 matrix? Good luck with that! No, but we need the building blocks so that one can specify such things as part of the language. >> I suspect that if your model became the law of the land, compilers would >> generate very bad code for any cases like the ones you want, and you >> wouldn't be able to use the result anyway. > > Nobody tried. But I doubt it. My proposals have a goal to significantly > simplify the language. Ada 2005 and 2012 added a huge number of special > cases requiring special treatment. That surely complicates optimization of > Ada programs which is already not great. Smaller and more regular language > would be easier to optimize. The definition of the language doesn't have much effect on the ability to optimize (almost everything that does is in the infamous 11.6). Optimization is almost completely done on language-independent intermediate codes, so the language definition only comes into play if some normal optimization has to be blocked (there are a few cases of this in Ada). A simpler definition *might* be easier to interpret and convert to that intermediate code, but it is just as likely that it would have to be completely implemented by run-time structures (like type tags) that defy optimization. ... > This is a totally bogus argument. OO imposes no overhead on specific > types. That's kool-aid invented by the Ada 9x team. It's not remotely true, especially as all usable OOP types have to be controlled. ... > Nobody proposes to change tagged types. The idea is to add classes to > non-tagged types by adding tag to the class-wide object while keeping > specific objects as-is. But there is no point in doing so. Inheritance of operations of discrete types is a bad idea that Ada already has and is virtually useless. Why go further down a path to nowhere? ... >>> Container libraries need to be implemented as well. I don't want to >>> expose >>> access type, I want referential semantics. >> >> And that's the point of 4.1.5. The only thing you can't do is write "new" > > (what about 'Access? What about Unchecked_Deallocation?) Huh? Unchecked_Deallocation is a procedure, and you surely can write a procedure. Since you can't use new, there is no point in using the predefined unchecked_deallocation anyway (it only works on objects allocated by new). If you really need these things, use storage pools and don't even think about changing the access values. I don't see any way to use 'Access with a safe abstraction; it's always illegal so you have to use 'Unchecked_Access and create dangling pointers. >> that way, but calling a function to do that doesn't seem that bad. > > How do I put such a reference in an array, for example? 4.1.5 would be > extremely difficult to use for intended purpose. It's just a tagged object, do with it what you want. I don't see why you think there is a problem. ... >> Ahh, but that was a case where the "existing semantics" was good enough >> so >> we didn't create a new thing. This is a very special access type, one >> that >> almost never can be copied -- for practical purposes it can only be >> dereferenced. That's what we needed. Note that there is no intent that >> anyone ever create an object for this access type (and that is where all >> of >> the problems lie). It just has the syntax of an access type so we didn't >> have to invent a new thing to get dereferencing. > > You have a very specific use case in mind, namely containers. There is a > whole world outside that, for which what you said is untrue, e.g. for > smart > pointers. The thing not only exposes access, it also exposes the target > type. You have to expose the target type in order to have strong typing. How could you hide it and still make type checks? > For smart pointers and handles you might what to hide both. Consider > a handle to a file. You certainly don't want to make File_Descriptor it > points to, visible. You want the handle to implement file I/O interface > routed privately to the descriptor. You also want handles be copyiable and > comparable, but treated as references to some opaque limited object. I don't see the problem -- here the target type would be private (that Ada's for "opaque", of course). And in all honesty, if you want an opaque handle, I don't see any reason that you would want to do a visible dereference of it. The ONLY reason that we need 4.1.5 is so that we can assign directly into the target type. For all other purposes, accessor functions work just as well, so you would be better off using them in such cases. Needing to write into parts of objects accessed by handles is a container-like problem. In other cases, using regular Ada 95-style code works just fine (as we did in the Ada 2005 version of the containers library). ... >>> Even if it were compile-time it would require same representation for >>> all >>> involved objects. How would I do it for Unsigned_1 and String? >> >> I don't see this necessarily. You certainly can use dispatching to >> support >> different representations. > > No way. Consider operation Send: > > procedure Send (To : in out Register; Value : Unsigned_1); > > procedure Send (To : in out Register; Value : String); > > It cannot dispatch! Firstly, Unsigned_1 and String are not in the same > class. Secondly, even if they were, it would be MD! So, you need MI and MD > to make it happen. Without them, poor man's solution is messing with > generics. If you really wanted to go this way, you'd put all of those types in the same class. (Having every possible advantage without any disadvantages is impossible.) You are right about multiple dispatch in some cases, although it's usually possible to layer those: procedure Send (To : in out Register; Value : Data'Class); which is legal Ada. You then have to dispatch to somehow marshall the values (streams would work in this case, although you'd probably want to have a private version for your own use). I admit I don't see any point to a tagged Register type, but I take your word for it that there is some value to that. ... >> I think >> these need a balance, especially as modern static analyzers can remove >> the >> vast majority of them (or warn that they might fail, which is a cause for >> concern). > > It is not about removing checks, though performance is a concern too. The > major problem is that failed checks must be flagged as errors. You are a > compiler writer, I am designing automation systems. To me run-time check > is > much too late. A fault can break real things, apart from maintenance. > Imagine Claw running on an oil platform. Do you own a helicopter? That's my point about static analysis. Such a tool should be able to prove that the majority of run-time checks can't happen, and give you a list of those remaining. (That's assuming appropriate declarations and assertions, of course). The only ones that you have to worry about are those that can't be proved. Of course, that depends on the underlying platform. If Claw is running on an oil platform, you've got problems because that's running on top of Windows. And we can't guess why or when Windows will fail something. So pretty much everything comes down to run-time checks. You can mitigate problems with run-time checks with last-chance error handlers and the like. But I'd prefer to prove they don't happen -- without constraining the language and programs to the point where you can't write anything realistic (the SPARK problem). That appears like more run-time checks (in terms of how you write the code), but the ultimate result is just as safe (and much less complicated, so it's a lot more likely to be right -- I'd never trust any program with more than a handful of generics, it's just too hard to get the compilers to handle those right). Randy.