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-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,c1131ea1fcd630a X-Google-Attributes: gid103376,public From: Ken Garlington Subject: Re: To Initialise or not Date: 1996/05/10 Message-ID: <31937B57.5B0@lmtas.lmco.com> X-Deja-AN: 154207636 references: <318508FE.204B@sanders.lockheed.com> <31933B50.687D@lmtas.lmco.com> content-type: text/plain; charset=us-ascii organization: Lockheed Martin Tactical Aircraft Systems mime-version: 1.0 newsgroups: comp.lang.ada x-mailer: Mozilla 2.01 (Macintosh; I; 68K) Date: 1996-05-10T00:00:00+00:00 List-Id: Robert A Duff wrote: > > By the way, in many cases, I do indeed use a special name for null for > each access type. I declare "No_Particular_Doctor: Doctor_Ptr := null;" > or something like that, and always use No_Particular_Doctor instead of > null. Given that you don't really use the _literal_ "null", I can see where your coding technique adds readability - in particular, if you define Doctor as its own data abstraction class, such as package Doctor is type Object is ...; type Reference is private; function New_Reference ( With_Contents : Object ) return Reference; function Contents ( Of_Reference : Reference ) return Object; function No_Particular_Doctor return Reference; Reference_Access_Error : exception; -- contents of uninitialized Reference Undefined_Doctor_Error : exception; -- contents of Reference = No_Particular_Doctor Object_Storage_Error : exception; -- unable to create new Reference private type Reference is access Object; end Doctor; (I suppose you could also make this a generic instantiation, with a little work.) However, in my mind, you're no longer talking about the desirability of using explicit null -- you're talking about the desirability of using meaningful names for a use of null, and potentially hiding the fact that you're using _any_ particular underlying type (an access type). Certainly, once you have Doctor.Reference as a private type, it should be easy to convert from access values to integers - in fact, ideally, you don't have to change any of the code that declares or uses Doctor_Ptr objects! (You could also readily switch to access values outside of the heap, for that matter.) I think there's something subtle here. In my mind, saying "I don't want to _use_ the literal null, since I want to reserve that to mean 'uninitialized'" makes some sense. I feel that's different from saying, "I want an explicit _initialization_ of the literal null to mean something different than the implicit _initialization_ to null." > (Same problem with any other coding convention -- if you don't > obey it, you'll end up with a mixture of No_Particular_Doctor and null, > causing confusion.) Of course, depending on how you write the Doctor abstraction, you can _enforce_ this coding convention, and avoid any possible confusion. > No, I wouldn't do that [directly preserve access_check behavior]. I would > rely on pragma Normalize_Scalars, or > else rely on the normal way of detecting uninitialized integers -- be > careful. Well, if you do the former, you still might have to visit each unitialized case to ensure that a valid out-of-range value exists (although in this example, it's a pretty sure bet.) You would also have to add 'Valid to get reliable checking, so I'm not sure I see the advantage of just adding the pragma. As far as the latter case, you could make the same argument for your coding standard -- instead of providing hints to the user, you could just admonish them to "be careful." It seems to me that, if the explicit initialization is to mean something, then the lack of explicit initialization should mean something, as well, and that this meaning should be carried forward in the translated software. > If I really did want to encode detection of the uninit integers in the > program, I would use a different value than the one meant to encode > "null". To really get that right, you'll have to wrap the integer in a > record, since only records allow user-defined default initial values > (unfortunately). And that might well be too much trouble. It might > even introduce bugs, since access types and integers are always passed > by copy, whereas records might be passed by reference. On the other hand, if you export No_Particular_Doctor from the Doctor class, you could go further and do the following: (1) When it's implemented as a pointer, have No_Particular_Doctor be implemented as an access to some dummy value. This way, you could use null to mean uninitialized, and No_Particular_Doctor to mean "no doctor assigned." (2) When it's implemented as an integer, have No_Particular_Doctor be an in-range value, but a never-used entry in your table. That way, out-of-range values (from Normalize_Scalars) would mean uninitialized, and No_Particular_Doctor would mean the same as in #1. This, to me, would make sense. However, this is not a "coding standard" to my thinking - this is a design abstration technique. I agree that the abstraction principle is quite valid, and very powerful (particularly in Ada, where it can be enforced as part of the contract model). > No such tool is going to do a decent job when it comes to heap data. I'm not sure that the tool has to do a particularly thorough job, just to find out the information you're attempting to convey with the literal null. However, we can agree to disagree on this. -- LMTAS - "Our Brand Means Quality"