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/08 Message-ID: <3190A8D3.3D53@lmtas.lmco.com> X-Deja-AN: 153797071 references: <318508FE.204B@sanders.lockheed.com> <3185E379.7C20@lmtas.lmco.com> <318E3A26.3565@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-08T00:00:00+00:00 List-Id: Robert A Duff wrote: > > Let me ask you this: Suppose Ada had a rule that all integers were > default-initialized to T'First, where T is the subtype of the variable. > Would you be happy with that language? Would it change the way you > write code? I would be happy with that language (ignoring the resource utilization effects), and any time I had an integer that I needed to initialize to T'First, I would leave off the initialization (knowing that it was going to be set to T'First anyway). Why not? > >However, I think you've missed my point. Let me retry: Do you have a block > >of comments in each compilation unit that says: > > > >-- NOTE: When a declaration using an access type has an explicit initial > >-- value of null, this means that the declared object can be used without > >-- any further initialization. > > No, of course not. It only needs to be stated once. Where? > And there are lots > of other things that need to be stated once, and you need to give the > reader some way of easily finding that place. Could you give some examples? > I freely admit that if > somebody doesn't understand the coding convention, it won't help them > understand the code. (It probably won't hurt, either, though.) I disagree. Any time I maintain code that does something non-obvious, I have to stop and figure out why the code was written in the strange manner. (Did he really just set that pointer to null, or did I misread "null"?) > In this example, I meant that it is safe to pretend that Ada doesn't > initialize pointers. Please re-read what I wrote in this light -- that > is, when I said "THIS is safe", I meant "THIS PRETENSE is a safe > assumption". I disagree. Re-read my comments about valid access objects which can be named similarly to null. In a more general sense, the more (unnecessary) code written, the greater the likelihood of error. > > This hypothetical not-quite-Ada language was an attempt to answer your > comment saying that it is hard to understand *what* the coding > convention *is*. It's *not* hard, if you're capable of imagining such a > language. And you have the context of this discussion. Without your explanation, within ready reach of the reader, it is quite difficult to guess the magic intent of the explicit initialization to null. At least, it is for me. > It doesn't make sense to answer this hypothetical explanation with, > "But, in Ada 95, pointers *are* initialized to null. The RM says so." But it does make sense to ask, "How does the reader get this explanation?" It's in some "central" place, apparently, but that's all I know so far... It also does make sense to ask, as I did originally, "Why is this convention useful?" I'm still not sure I see that part of the discussion... > By the way, all your examples concerned local variables. The more > interesting cases are package-body variables, and record components. Then present an example of either type, showing why this convention conveys useful information. > No, no, no. That's not what I meant about "safe". Of course implicit > null's are just as safe as explicit nulls. Safer, IMHO. > It just seems to me that it's valuable to know whether a given value is > going to be used. It makes the code more readable, IMHO. I guess I would be more convinced with an actual example. Does this approach extend to other cases? For example, suppose a record object is being assigned with an aggregate, and some of the aggregate values will be used in the code, and others will be overwritten first. Do you have some mechanism for distinguishing them? What about loops? When I write "for J in Buffer'Range loop", there's an implicit initialization of J to Buffer'First. Is there an issue here? It just seems like a strange way to represent data flow information. > In this case, the Ada *language* is what violates the KISS principle. I > understand the reasons behind it, but still, the rule is that some > variables get a "junk" initial value, and some variables get a > well-defined initial value (by default, of course), which is obviously > more complicated than treating all variables the same. However, if you want all (scalar) variables to get a well-defined default initial value, you can do that in Ada 95 with Normalize_Scalars (and 'Size), right? I don't know why this is critical for you, but it's there if you want it... > I claim that the coding convention we're arguing about is actually > *more* KISS, since it treats integers and pointers alike. I disagree that consistency necessarily equates to simplicity. (See the example below). > >I understand that you want pointers to act like integers. I just don't > >understand _why_, since pointers are conceptually different from integers. > > I don't see any way in which integers and pointers are different with > respect to *this* issue (whether or not they should be initialized). Well, assuming you don't resort to Unchecked_Conversion or something nasty like that, any cases I can think of where you can use integers to reference a memory location will automatically have bounds (e.g., as an array reference). Pointers are unbounded in Ada 95, as far as I can tell -- there is no easy way to check for "in range" in a machine-independent fashion. Therefore, to avoid illegal references, you have to do something special, right? > >Here's a different example: Suppose you saw code that looked like: > > > > X : Integer := Init (Thousands => 1, Hundreds => 4, others => 0) > > -- set X to 1400. > > > >Would this be a preferred approach, since I'm just creating numeric literals > >the way I create array aggregates? > > Sorry, but you lost me there. To slightly misquote a famous man: "I claim that the coding convention I'm proposing is actually *more* KISS, since it treats integers and arrays alike.... I don't see any way in which integers and arrays are different with respect to *this* issue (how they should be initialized)." However, applying my guideline that you don't write extra code unless there's a clear purpose, this coding convention for integer initialization is silly. It doesn't communicate, it obfuscates. > > >> But initializing all access values to null does > >> *not* constitute a "reasonable" initial value, in many cases. > > > >This is certainly true. However, can you identify a case where null _is_ a > >reasonable initial value, but not a reasonable initial _default_ value? > > Sure. I have a hard time imagining a type that is otherwise. > > Suppose (stealing from another thread;-)) we have Patients and Doctors. > Each Patient is represented by a record, containing (among other > things), a pointer to its Doctor. Because of the way this application > works, you can't create a Patient without giving it a Doctor -- i.e. > there is no reasonable default value for the Doctor field, and it must > always be non-null. Wait a minute! In this case, null is neither a reasonable initial value, nor a reasonable initial default value. Therefore, it is not a valid example. > However, there's a hash table, implemented as an array of pointers to > Doctors. I want to initialize all the slots to "null", which means > "this slot is empty now". Conceptually, the array elements should be > initialized to null, whereas the My_Doctor field of Patient should be > initialized to "Don't touch this!". Wait a minute! In this case, null is both a reasonable initial value, and a reasonable initial default value. Therefore, it is also not a valid example. > I would write ":= (others => null);" on the array, to signify that I > intend to *depend* upon the initial null value, but I would *not* write > ":= null" on the My_Doctor component of type Patient, to signify that I > intend to always explicitly initialize it. Now, consider both of the following: 1. When I read the Patient data structure, how important to me is it to know that Doctor should never be null? Wouldn't this be better as a comment (or even an assertion) within the code which creates Patients, since that's probably where I need to know this information? 2. Suppose I change the application slightly, such that a Patient is created when they enter the waiting room. In this case, it may be quite valid for a Patient to exist, but not have an associated Doctor. In order to maintain your coding convention, the maintainer must go back to the Patient record and add an explicit initialization. Is this likely to happen, particularly if the code is separated from the data structure, and nothing will happen functionally if the maintainer fails to do this? Or will your coding convention "drift" over time, causing more confusion? So, here's my summary: 1. The convention is not self-evident. It has to be explained somewhere. If the maintainer fails to get that understanding, it will cause confusion while (s)he searches for the meaning to this "useless" code. 2. Even if the convention is understood, its value is hampered by the fact that it doesn't convey information at the point where it is needed (the algorithm using the data structure). 3. As a corollary to #2, further maintenance of the code makes it easy for the coding convention to be inconsistently applied. This further obfuscates the code. 4. Because it is "active" code which the compiler analyzes (unlike a comment), there is also the danger (admittedly slight) of a coding error being introduced. Overall, I stand by my original statement: I don't see the attraction of this style. -- LMTAS - "Our Brand Means Quality"