[comp.lang.ada] Initialization

mfeldman@seas.gwu.edu (Michael Feldman) (06/14/90)

I have a rationale-type questions regarding an apparent irregularity
in Ada, namely in the area of default initializations.

- We know that a _variable_ can be initialized in its declaration, e.g.
   X: T := some_expression;
where some_expression need not even be static. [digression: over-use of
this can be risky IMHO because of nastiness if some_expression manages to
propagate an exception - the point is that initialization is permitted].

- We know that the components of a _record_ type can be default-initialized
in the definition of the record type, e.g.
   type R is record
     F1 : T1 := something;
     F2 : T2 := something_else;
   end record;
where some thing something_else can be e.g. aggregates.

I don't remember having seen any discussion on the group about why other
types cannot be default-initialized, e.g.
   type Little is range -10 .. 10 := 0;
or
   type Vector is array (1..10) of float := (1..10 => 0.0);
or even
   type Vector is array (integer range <>) of float := (others => 0.0);

The last 3 examples are not permitted; it's obvious at least to me that
there would be great benefit in permitting them. What are the costs?

Can someone speak authoritatively about why this irregularity exists? The
Ada Rationale gives a nice justification of default initializations (for
record types, of course) but doesn't say boo about why, if they are so
valuable, they are not allowed uniformly. I'm one of these guys who always
wonders why irregularities in _designed_ languages exist. There is usually
a pretty good reason, but in this case it certainly isn't obvious.
(Irregularities even in natural languages often have good linguistic reasons).

Thanks for whatever enlightenment is forthcoming.
---------------------------------------------------------------------------
Prof. Michael Feldman
Department of Electrical Engineering and Computer Science
The George Washington University
Washington, DC 20052
+1-202-994-5253
mfeldman@seas.gwu.edu
---------------------------------------------------------------------------

firth@sei.cmu.edu (Robert Firth) (06/15/90)

In article <1957@sparko.gwu.edu> mfeldman@seas.gwu.edu (Michael Feldman) writes:
>I have a rationale-type questions regarding an apparent irregularity
>in Ada, namely in the area of default initializations.

There is no good reason for the irregularity.  Since a record
component can be of any type, the implementation of

	record
	  Component : Thing := Initial_Value;
	end record;

is no more and no less difficult than the implementation of

	type Thing is Type_Definition := Initial_Value;

would be.  There are no serious parsing difficulties with the
above syntax, and no additional semantic issues.

The reason for the irregularity is historical.  In the original
Green language, the syntax of a record type definition read

	record_type_definition ::= RECORD component_list END RECORD

	component_list ::= {object_declaration} [variant_part] | NULL ;

Because the syntax of object_definition was reused, the ability to
initialise the component got carried over automatically.  When this
was noticed, it was decided that this was a useful thing to have.

I recall asking Jean why he didn't make the type model more regular
by allowing all types to have initialisation expressions, and his
reply was that you could always achieve this effect by nesting the
type you wanted in a record, and he didn't want to add extra syntax.
Please do not ask me to defend this position.

murphy@mips.COM (Mike Murphy) (06/15/90)

In article <1957@sparko.gwu.edu> mfeldman@seas.gwu.edu (Michael Feldman) writes:
>I don't remember having seen any discussion on the group about why other
>types cannot be default-initialized, e.g.
>   type Little is range -10 .. 10 := 0;
>or
>   type Vector is array (1..10) of float := (1..10 => 0.0);
>or even
>   type Vector is array (integer range <>) of float := (others => 0.0);

I question how useful type initialization is given that we can easily
initialize variables, but I agree that it is an irregularity to only
allow it for record types.  When I first read this question I thought,
yea, that should be easy to do.  But then I thought of some complications.

To take your above example, suppose we later said:
	subtype PosLittle is Little range 1..10;
	p : PosLittle;
What is p initialized to?
If we implicitly initialize p to 0 we should raise constraint_error;
is that acceptable?

A related issue is initializing unconstrained arrays; either we limit
the initialization to the others clause, or we have situations like:
	type Vector is array (integer range <>) of float := 
		(0 => 0.0, others => 1.0);
	v : Vector(1..10);
What happens here?  Either we could raise constraint_error because there
is an initialization to a component outside the range of v, or we could
treat it like a variant part of a record that is not used and just ignore
that part of the initialization.  Which brings up the fact that type 
initialization is not free; it often requires building an implicit
procedure that the compiler calls to dynamically decide how to initialize
the object.

A last case is initializing access types; is anything other than "null"
a legal initial value, e.g.
	type astring is access string := new string'("void");
	a : astring(1..3);	-- constraint_error?

-- Mike Murphy
-- UUCP: sun!decwrl!mips!murphy or murphy@mips.com

mfeldman@seas.gwu.edu (Michael Feldman) (06/15/90)

In article <7540@fy.sei.cmu.edu> firth@sei.cmu.edu (Robert Firth) writes:
> 
> I recall asking Jean why he didn't make the type model more regular
> by allowing all types to have initialisation expressions, and his
> reply was that you could always achieve this effect by nesting the
> type you wanted in a record, and he didn't want to add extra syntax.
> Please do not ask me to defend this position.

Don't worry. If this is the extent of the reasoning, it's entirely
indefensible IMHO. That's the way it goes. Sigh...
---------------------------------------------------------------------------
Prof. Michael Feldman
Department of Electrical Engineering and Computer Science
The George Washington University
Washington, DC 20052
+1-202-994-5253
mfeldman@seas.gwu.edu
---------------------------------------------------------------------------

mfeldman@seas.gwu.edu (Michael Feldman) (06/15/90)

In article <39390@mips.mips.COM> murphy@mips.COM (Mike Murphy) writes:

> 
> To take your above example, suppose we later said:
> 	subtype PosLittle is Little range 1..10;
> 	p : PosLittle;
> What is p initialized to?
> If we implicitly initialize p to 0 we should raise constraint_error;
> is that acceptable?
Sure. Sounds OK to me. But you're right - the subtype issue does complicate
matters a bit.
> 
> A related issue is initializing unconstrained arrays; either we limit
> the initialization to the others clause, or we have situations like:
> 	type Vector is array (integer range <>) of float := 
> 		(0 => 0.0, others => 1.0);
> 	v : Vector(1..10);
I'm sure a counterexample could be found, but I guess I would allow only
"others" aggregates for unconstrained array types. Explicitly supplying an
index for something whose index range is undefined is not a sensible
thing to do, it seems to me.

> [ . . . ]                         Which brings up the fact that type 
> initialization is not free; it often requires building an implicit
> procedure that the compiler calls to dynamically decide how to initialize
> the object.
Indeed. But there are many areas requiring this sort of dynamic decision
anyway.
> 
> A last case is initializing access types; is anything other than "null"
> a legal initial value, e.g.
> 	type astring is access string := new string'("void");
Hmmm. I'd advocate against this kind of dynamic initialization even if
it were a variable declaration. If Storage_Error were raised, for example,
the exception would undoubtedly propagate to an undesirable place.
(since it would be raised in an elaboration, the current frame's handler
can't handle, therefore the exception propagates).
Might be legal, but not a good idea. This is what I argued in my last
posting: initializations can be good, but can be too powerful for their
own good if used over-zealously.

> 	a : astring(1..3);	-- constraint_error?
                   ^^^^^^^ Hmmm. I wasn't aware that one could supply a
constraint this way. For a string, sure. For an "access to string", is
this legal Ada (i.e. the implicit "new")? If so, I just learned a new style.

Mike Feldman

stachour@sctc.com (Paul Stachour) (03/28/91)

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:

>I would rather see features that help people detect or avoid the error
>of using an uninitialised variable rather than features which define
>the problem away.  For example, if arrays with fill pointers were a
>standard part of the language (perhaps defined as a standard package),
>then we'd be close enough to Dijkstra's arrays to get some of the
>protection without being too far from the kind of array already present.

>Don't expect default initial values for types to be an unmixed blessing.

As one who has programmed regularly in more than an half-dozen languages,
and has worked on teams that have implemented 3 compilers for different
lanauges, I agree.

If you have a variable that is unitialized, then a good flow anyalysis
tool (we had some inside one of the compilers) can follow your
control-flow and give you "used before set" messages.  When you do
have something initialized, it is, by definition, set.  Thus the
flow-analysis gives you nothing.

I long for the (ancient) FORTRAN II compiler I used on an IBM 7074
in the mid-1960s.  It set all of the words in the machine to an
"invalid pattern" before beginning your program.  And then if you
fetched anything that hadn't been set, you took a hardware fault and
the run-time told what you were doing wrong.

Much like Saber-C and other good c-interpreters can do today,
but with hardware support.

One problem is when you have an uninitialized item as a component
of a struacture and you assign one instance of the structre to another.
Do you get a fault or not.  You really aren't "using" the item yet.

Enjoy. ...Paul
-- 
Paul Stachour          SCTC, 1210 W. County Rd E, Suite 100           
stachour@sctc.com          Arden Hills, MN  55112
                             [1]-(612) 482-7467