> I find that it is really not a good design choice to initialize
> every reference in all ML-like languages (yes, I well realize
> the difficulty in not doing so). Here is my argument.
[...]
> (1) ML strategy: initialize x with any value 'v' of an appropriate
[...]
> (2) Java Strategy: let us say we have the same scenario as before
> but 'x' is not initialized. If I read from x before assigning a value
[...]
> Can you still say that the ML strategy is better than the Java
> strategy?
Yes, I can.
> I thus argue that it is better using dynamic checking
> to detect reading from uninitialized reference than simply
> assigning a value to every reference upon its creation.
>
> To summarize, my bottom line question is: what is really achieved
> by assigning a reference a (wrong) initial value? Isn't this just
> like an ostrich solving its problem by burying its head in sand?
>
> Of course, another problem with the ML strategy is efficiency loss
> (which, though, is often negligible as discussed here before)
The ML style is better, since the default regime is to initialize
references and in most cases, you perfectly know the correct
initialization value at creation time.
For the few remaining cases, where you cannot guess the initial value,
then you must use another scheme that indeed involves dynamic testing;
I will not consider initialization with ``any value 'v' of an
appropriate type'' as a receivable solution, since this ``solution''
is far too error prone (as you had already mentioned).
Another well-known trick to initialize references is to use
options. At creation time you define the reference as being ``ref
None'', and later assign it to ``Some v'', when v can be computed.
Then in your program you have to pattern match the contents of the
reference to get its value, and raise an exception if necessary,
getting the Java semantics.
To elegantly handle this new scheme, you may even write a new
dereferencing prefix operator:
let ( !! ) r =
match !r with
| None -> invalid_arg "not yet initialized"
| Some v -> v;;
Then you just substitute !!r to !r into your program.
One step further is to aly define a new assignment operator to hide the
``Some'' manipulations:
let ( =: ) r v = r := Some v;;
Now, for instance:
let r = ref None;;
r =: 1;;
r =: 2 + !!r;;
This way, the ``cannot initialize my reference at creation time''
problem, is somewhat solved, but still evident in your code (and this
is a good property, since there is a real difficulty in your source
code, that can raise an exception when accessing the ``r'' reference).
Conclusion: I prefer the ML style, which elegantly solves the common
case and let you encode fairly simply the hairy cases. The efficiency
loss problem deceives the same remark and the same solution: there is
no loss in the most common case (in that case you know what is the
initial value and have to compute it anyway), and in the hairy cases
you can use the None/Some trick, an this hairy case is evident in the
source code.
Pierre Weis
INRIA, Projet Cristal, Pierre.Weis@inria.fr, http://cristal.inria.fr/~weis/
This archive was generated by hypermail 2b29 : Thu May 11 2000 - 17:46:02 MET DST