Version 1.1 of acs/ac-00026.txt

Unformatted version of acs/ac-00026.txt version 1.1
Other versions for file acs/ac-00026.txt

!standard 4.06(01)          02-01-23 AC95-00026/01
!class amendment 01-12-28
!status received no action 02-01-23
!subject User-defined type conversion
!summary
!appendix

From: Randy Brukardt
Sent: Friday, December 28, 2001  7:24 PM

For the four thousandth time, I'm writing something like:

    function String_of (Name : in Face_Name) return String;
        -- Returns a string representation of the face name Name.

and I can't think of a decent name. It really should be "String", because
its a conversion, but that won't work for those using use clauses.

Similarly, the conversion from String to Face_Name really ought to be called
"Face_Name":

    function Face_Name_of (Name : in String) return Face_Name;

Shouldn't we be allowed to define conversions between composite types that
wouldn't otherwise have them? That is especially useful for private types.
Or better yet, "constructors" a-la C++?


Ada already allows overloading of type conversions and subprogram calls,
provided that the declarations are not in the same declarative region:

  package Font is
    FACE_SIZE : constant := 32;
    type Face_Name is array (1 .. FACE_SIZE) of aliased Interfaces.C.Char;
    package Nest is
       function Face_Name (Name : in Standard.String) return Font.Face_Name;
       function String (Name : in Font.Face_Name) return Standard.String;
    end Nest;
  end Font;

  with Font;
  procedure Test is
     use Font, Font.Nest;
     Value : Font.Face_Name; -- Can't say "Face_Name" here, a use clause conflict.
  begin
     Value := Face_Name (Name => "Arial"); -- Calls Font.Nest.Face_Name.
     declare
        Name : String := Nest.String (Value);
     begin
        ...
     end;
  end Test;

Note that a single parameter positional call to Face_Name is ambiguous with
a type conversion,
but otherwise it allowed in Ada. (A type conversion essentially resolves as
a single parameter function which takes "any type".) OTOH, "String ()" is
always a type conversion (except in Font.Nest), because String is declared
in Standard, and thus is directly visible.

Thus, it is possible to provide this capability without changing resolution
at all. The main problem is to eliminate restrictions on where
"constructors" can be declared. We want to be able to declare constructors
with the type they construct.

This could be done without any incompatibilities as follows (warning, this
is a rough proposal, not a fully fleshed out one).

Define a type declaration as "partially overloadable". Define a "partially
overloadable" declaration to never be a homograph of an "overloadable"
declaration.

The effect would be to allow subprograms ("callable entities") to overload
types in the same declarative region, but otherwise leave the rules alone.
The changes would only make currently illegal programs legal, so there would
not be any compatibility problems.

We'd also probably want to allow one "partially overloadable" to be use
visible simultaneously with one or more overloadable entities. (That would
allow "Value : Font_Name;" in the example above; the fact that it isn't
legal is weird). Again, only illegal programs would be made legal.

This wouldn't solve my original problem for people who use use clauses. I
doubt that problem can be solved, mainly because of the "always visible"
nature of types in Standard. That means that the conversion/constructor
would never be directly visible. However, it would come close to solving the
problem for user-defined types.

The only problem that I see with this is that it wouldn't allow positional
single parameter calls (such a call would always be ambiguous with a type
conversion). A preference rule for a subprogram call over a type conversion
would work, but those always seem to have Beaujolais problems. Perhaps not
in this case (as the overloading is limited). This requires more study.

Anyway, is this idea worth pursuing?

****************************************************************

From: Robert Dewar
Sent: Saturday, December 29, 2001  6:10 AM

I must say that I find the name To_String to be perfectly fine, and in fact
preferable to the use of String in this context.

****************************************************************

From: Robert Duff
Sent: Monday, December 31, 2001  10:37 AM

> Ada already allows overloading of type conversions and subprogram calls,
> provided that the declarations are not in the same declarative region:

No, that's not right.  There is never a place where a type X and a
function X are simultaneously directly visible.  One or the other can be
directly visible, or neither.

...
>      Value := Face_Name (Name => "Arial"); -- Calls Font.Nest.Face_Name.

No, that's currently illegal for the same reason, namely ``-- Can't say
"Face_Name" here, a use clause conflict.''

> Note that a single parameter positional call to Face_Name is ambiguous with
> a type conversion, but otherwise it allowed in Ada.

No, that's not right.  There is never an ambiguity between a function
name and a type name, because it is impossible for them to both be
directly visible.

> This could be done without any incompatibilities as follows (warning, this
> is a rough proposal, not a fully fleshed out one).

I don't see how you can avoid incompatibilities (and/or Beaujolais
effects and/or other error-prone rules).  Eg:

    procedure Main is

	package P is
	    type X is private;
	    type Y is new X;
	end P;

	package Q is
	    function X(Param: P.Y) return P.X;
	end Q;

	package body P is
	    Y_Var: Y;
	    use Q;
	    X_Var: X := X(Y_Var); -- Legal?
        end P;

The above is legal Ada 95.  The "X(Y_Var)" is a type conversion.
Function X is not visible at that point.

It seems that function X would be visible in the new proposal,
thus causing an incompatibility.  Or is there a preference rule?
If we prefer type_conversions over function calls, the above is
error-prone.  If we prefer function calls over type_conversions,
it is also error-prone, and in addition, the above program changes its
run-time behavior.  A preference either way is error-prone, because
how do we know which one the user *meant*?  Furthermore, I think
such a preference rule causes Beaujolais.

Now the above example is questionable, because the type_conversion is
legal.  Your goal of course is to define a function that can be used
when a normal type_conversion would *not* be legal.  So perhaps you
want some rules saying the function is only allowed (or only visible,
or only resolvable-to) in cases where the type_conv is not legal.
But the type_conv rules are not currently Name Resolution rules,
and for good reason: they're way too complicated.  I wouldn't want
to change that.

In other words, the current resolution rule for type_conversions is that
they accept any type.  Unless you change that, you could never call the
function, because the type_conv would always be an "acceptable
interpretation".  But if you *do* change that, you're adding an
awful lot of complexity.

> Define a type declaration as "partially overloadable". Define a "partially
> overloadable" declaration to never be a homograph of an "overloadable"
> declaration.
>
> The effect would be to allow subprograms ("callable entities") to overload
> types in the same declarative region, but otherwise leave the rules alone.
> The changes would only make currently illegal programs legal, so there would
> not be any compatibility problems.
>
> We'd also probably want to allow one "partially overloadable" to be use
> visible simultaneously with one or more overloadable entities. (That would
> allow "Value : Font_Name;" in the example above; the fact that it isn't
> legal is weird). Again, only illegal programs would be made legal.

I skept.  This is one case where I wouldn't believe any such
pronouncments without seeing the actual RM wording.  (And you know
I often say fiddling with wording is a waste of time.  ;-))

> This wouldn't solve my original problem for people who use use clauses. I
> doubt that problem can be solved, mainly because of the "always visible"
> nature of types in Standard. That means that the conversion/constructor
> would never be directly visible. However, it would come close to solving the
> problem for user-defined types.
>
> The only problem that I see with this is that it wouldn't allow positional
> single parameter calls (such a call would always be ambiguous with a type
> conversion). A preference rule for a subprogram call over a type conversion
> would work, but those always seem to have Beaujolais problems. Perhaps not
> in this case (as the overloading is limited). This requires more study.
>
> Anyway, is this idea worth pursuing?

I might relax the rules along the lines you suggest if I were designing
a language from scratch.  (E.g., why not make *everything* overloadable?
That's a simple rule.)

But in the context of Ada, I have to say no, this idea is not worth
pursuing.  Meddling with the visibility rules in order to solve a minor
naming issue is not a good idea.  "Partial overloading" is an extra
concept that will cause user's brains to hurt.  And compiler writers
will have to change some of the more subtle parts of their front ends.

I suggest you call it "To_String" or whatever, and not try to change the
language.

Actually, in the case of to/from String, I often use "Image" and "Value"
as the function names, by analogy with the attributes that do the same
thing for predefined types.

****************************************************************

From: Randy Brukardt
Sent: Monday, December 31, 2001  12:44 PM

> > Ada already allows overloading of type conversions and subprogram calls,
> > provided that the declarations are not in the same declarative region:
>
> No, that's not right.  There is never a place where a type X and a
> function X are simultaneously directly visible.  One or the other can be
> directly visible, or neither.

OK, rephrase that to "Ada compilers already..."...

> >   package Font is
> >     FACE_SIZE : constant := 32;
> >     type Face_Name is array (1 .. FACE_SIZE) of aliased Interfaces.C.Char;
> >     package Nest is
> >        function Face_Name (Name : in Standard.String) return Font.Face_Name;
> >        function String (Name : in Font.Face_Name) return Standard.String;
> >     end Nest;
> >   end Font;
> >
> >   with Font;
> >   procedure Test is
> >      use Font, Font.Nest;
> >      Value : Font.Face_Name; -- Can't say "Face_Name" here, a use clause
> >                              -- conflict.
> >   begin
> >      Value := Face_Name (Name => "Arial"); -- Calls Font.Nest.Face_Name.
>
> No, that's currently illegal for the same reason, namely ``-- Can't say
> "Face_Name" here, a use clause conflict.''

I compiled this program on GNAT and ObjectAda before posting it, and both
accepted the above call.

That does imply that care would be needed here, because we generally don't
want to enforce a rule more restrictive than what compilers already do
(irrespective of what the language says -- see the prefix of 'Access
discussion).

> I don't see how you can avoid incompatibilities (and/or Beaujolais
> effects and/or other error-prone rules).  Eg:
>
>     procedure Main is
>
> 	package P is
> 	    type X is private;
> 	    type Y is new X;
> 	end P;
>
> 	package Q is
> 	    function X(Param: P.Y) return P.X;
> 	end Q;
>
> 	package body P is
> 	    Y_Var: Y;
> 	    use Q;
> 	    X_Var: X := X(Y_Var); -- Legal?
>         end P;
>
> The above is legal Ada 95.  The "X(Y_Var)" is a type conversion.
> Function X is not visible at that point.

Of course. No rule ever would make a use visible item visible instead of a
directly visible one. Either both items have to be directly visible
(ignoring hiding), or both have to use visible.

(Thus the "String" business is unsolvable. But the constructor case is still
interesting...)

Thus any (existing) program change would be caused by adding a
construction-style function in the same scope as the type. (That's not
currently legal). So I don't think any existing programs would change
behavior.


>...
> I might relax the rules along the lines you suggest if I were designing
> a language from scratch.  (E.g., why not make *everything* overloadable?
> That's a simple rule.)
>
> But in the context of Ada, I have to say no, this idea is not worth
> pursuing.  Meddling with the visibility rules in order to solve a minor
> naming issue is not a good idea.  "Partial overloading" is an extra
> concept that will cause user's brains to hurt.  And compiler writers
> will have to change some of the more subtle parts of their front ends.
>
> I suggest you call it "To_String" or whatever, and not try to change the
> language.
>
> Actually, in the case of to/from String, I often use "Image" and "Value"
> as the function names, by analogy with the attributes that do the same
> thing for predefined types.

Careful! Next thing you know, someone will be asking for user-definable
'Image and 'Value attributes. :-)

****************************************************************

From: Randy Brukardt
Sent: Monday, December 31, 2001  3:36 PM

> > Value := Face_Name (Name => "Arial"); -- Calls Font.Nest.Face_Name.
> I compiled this program on GNAT and ObjectAda before posting
> it, and both accepted the above call.

Someone complained to me that they couldn't compile the program with GNAT,
so I did some further investigation. Apparently, I was misled by the
compiler's error handling: my test program was a B-Test, and no errors were
reported for the call on either GNAT or ObjectAda.

However, with everything but the call removed, the call does in fact report
an error.

Therefore I withdraw the entire "constructor" based proposal; it doesn't
solve the problem without way too much mess.

My original idea was user-defined conversions; that would look something
like:

    for Face_Names'Conversion use To_Face_Name;
    for Face_Names'Conversion use To_String; -- The reverse conversion.

The details would need some thought, but I believe it could be made to work.
(And it doesn't have any effect visibility).

****************************************************************

From: Robert Duff
Sent: Tuesday, January  1, 2002  9:38 AM

> My original idea was user-defined conversions; that would look something
> like:

That's idea sounds easier to make work.

But I still don't think it's worth the trouble.  I don't see a big
difference in readability between String(X) and To_String(X).

Now how about user-defined *implicit* conversions?

****************************************************************

From: Randy Brukardt
Sent: Friday, January 4, 2002  5:16 PM

> That's idea sounds easier to make work.
>
> But I still don't think it's worth the trouble.  I don't see a big
> difference in readability between String(X) and To_String(X).

Well, if we allow overriding existing conversions as well as adding new
ones, it would allow getting rid of conversions that you don't want. It
could be very useful for user-defined numeric types (such as unit
conversions).

As far as readability goes, I'm sure that you aren't claiming that it harms
the readability. But the big benefit is writing code that depends on canned
libraries. For those, you have to go rummaging around to figure out what the
name of the conversion routine might be. (It's unlikely that those libraries
use the same convention that you do.) Certainly Ada emphasizes readability
over writeability, but there certainly isn't any reason we can't make Ada
easier to write (as long as doing so doesn't harm readability).

> Now how about user-defined *implicit* conversions?

Well, I think you need an *explicit* conversion before you can talk about
*implicit* conversions. But I'm not sure how that would work (other than the
obvious case of Universal integer and universal real). And it seems to me
that implicit conversions may introduce incompatibilities as well (it would
have a substantial impact on resolution). But if you have something specific
in mind, I'd be happy to look at it at the same time.

****************************************************************

From: Robert Dewar
Sent: Friday, January  4, 2002  5:22 PM

I actually find that adding user defined conversions is likely to harm
readability. If i see

   x := string(b);

then (assuming string has not been redefined, which seems a reasonable
assumption), I know this is an ordinary type conversion without having
to look all over the place to see if a conversion called string has
been defined.

If I see

  x := To_String (b);

or

  x := Image (b);

then I know this is a user defined function, and I can go look at it.

<<libraries. For those, you have to go rummaging around to figure out what the
name of the conversion routine might be. (It's unlikely that those libraries
use the same convention that you do.) Certainly Ada emphasizes readability
>>

Sounds like it is the *writer* who has to do the rummaging, e.g. to find
out whether the name is To_String or Image. Indeed if we add user defined
conversions, the rummaging just gets incrementally worse, since now we look
not only for user defined functins but also user defined conversions.

I really don't see how the reader is much affected, except perhaps negatively
as postulated above, by this alledged "rummaging".

I really find this very odd (Randy's insistence on the value of this
feature). We certainly never had any users who expressed any interest
in such a capabilility (and we have users who are not at all shy about
saying what they want :-)

****************************************************************

From: Randy Brukardt
Sent: Friday, January 4, 2002  6:30 PM

> I actually find that adding user defined conversions is likely to harm
> readability. If i see
>
>    x := string(b);
>
> then (assuming string has not been redefined, which seems a reasonable
> assumption), I know this is an ordinary type conversion without having
> to look all over the place to see if a conversion called string has
> been defined.
>
> If I see
>
>   x := To_String (b);
>
> or
>
>   x := Image (b);
>
> then I know this is a user defined function, and I can go look at it.

Maybe, but that could be true at most for the predefined types, and since
the only predefined types that get used are String and Character, it doesn't
seem a major difference.

Certainly, if you see
    X := File_Kind (B);
you don't know if you have a function call or a type conversion without
looking up File_Kind. Indeed, I generally look at type conversions as a
function call with funny resolution. I don't see them as fundamentally
different, just predefined. Perhaps that is why I see this issue differently
than you.

This is really no different than overriding an operator in Ada. Certainly,
someone could redefine "+" to be multiply, but that would break the
abstraction. The same holds here. Usually, you don't need to know exactly
what the expression does, be it a type conversion, an unchecked conversion
of some sort, or a call to the National Archives. :-)

Of course, when debugging, you have check every item carefully. But this
wouldn't make it appreciably harder.

> I really don't see how the reader is much affected, except perhaps negatively
> as postulated above, by this alledged "rummaging".

They aren't. This feature is useful in two ways:
   Making better abstractions by better matching operations to functions
(and, as a side effect, providing a way to eliminate predefined
functionality that is inappropriate).
   Making it easier to write programs based on "canned" abstractions.

> I really find this very odd (Randy's insistence on the value of this
> feature). We certainly never had any users who expressed any interest
> in such a capabilility (and we have users who are not at all shy about
> saying what they want :-)

I asked several Ada users (at least one of whom is here) before publicly
floating this idea. (I was concerned that it was too complicated for the
benefit.) They all thought it was worth investigating. However, the silence
here now that I have done so is deafening. Perhaps they encouraged me to
investigate it for the amusement value in seeing me float such a dumb idea?
:-)

****************************************************************

From: Robert Dewar
Sent: Friday, January  4, 2002  6:59 PM

<<Maybe, but that could be true at most for the predefined types, and since
the only predefined types that get used are String and Character, it doesn't
seem a major difference.>>

Sometimes I think you are in a different world. If I grep customers code
for the predefined types, I will find zillions of uses of Boolean (I bet
that is true even of your code :-) I will also find lots and lots of
uses of Float, Integer etc.

And I don't see why what I say applies only to predefined types anyway.

>>I asked several Ada users (at least one of whom is here)

Do we really have Ada users here? In my experience the answer is close to
no :0-)

****************************************************************

From: Tucker Taft
Sent: Sunday, January  6, 2002  8:37 PM

I don't find the cost/benefit ratio very favorable for this idea.

On the other hand, user-defined subtype conversions (analogous
to the "sliding" conversions provided for array subtypes of the same length) is
something we talked about in the past, and could be quite useful
to deal with discriminated types, and arrays for that matter.

Now that we have this nice notion of "operational attributes," it
would certainly seem natural to use that feature for defining
additional capabilities like this.

Ideally any place that implicit array subtype conversion happens now
one could do a user-defined subtype conversion.  However, that is
difficult to support because there is no easy way to pass in the
constraints of the target, unless it already exists an object.  That
means that only an assignment statement to an existing object
would work well.  Hence, this would devolve into a user-defined
conversion-on-assignment-statement procedure.  That's probably OK,
because when passing parameters or initializing a stand-alone
object, it is easy enough to have the parameter or
object take its constraints from its initial value.  (That still leaves
unhandled the case of initializing a component, but you can't have everything!)

Hence, the proposal would be something like:

   procedure Asgn_Cnvt(Left : in out T; Right: in T);
   for T'Assignment_Conversion use Asgn_Cnvt;

This would be invoked when the left-hand side of an assignment
statement is a variable of type T, and the normal assignment
statement would raise a Constraint_Error due to mismatched
discriminant or length.  I considered just having an "Assignment_Statement"
attribute, but it is much more useful and efficient if the generated code
checks for the constraint/length mismatch, and only invokes the user-defined
procedure in that case.  Note that this procedure would be invoked
even for controlled types that have their own finalize/adjust routines.
The finalize/adjust would be invoked when the constraints match,
while this would be invoked when they mismatch.

For controlled types, it also might be nice to have an ability to special-case
assignment statements (and perhaps other usage contexts) even when
the constraints match.  This is probably better handled by adding another
primitive operation to the Controlled type.  For example:

   procedure Assignment_Statement(
      Left : in out Controlled; Right : in Controlled);

If overridden for a particular controlled type C, this would be invoked
when the constraints match and the left-hand side of the assignment
is C, instead of the usual finalize/copy/adjust.  This would allow the reuse
of levels of indirection allocated for the left-hand side, rather than having
them released as part of a call on Finalize.

Alternatively, this matching-constraint assignment could be specified using
an operational attribute, and then it would allow assignment statements to
be user-defined for any kind of type, even when constraints match.
I can't see much value for a non controlled type, but because this is only for
assignment statements, it could be relatively easily implemented without
requiring any of the cleanup lists or other per-object overhead associated
with controlled types.

****************************************************************

From: Robert Duff
Sent: Sunday, January  6, 2002  10:25 AM

> Do we really have Ada users here? In my experience the answer is close
> to no :0-)

I am an Ada user, among other things.

****************************************************************

From: Pascal Leroy
Sent: Monday, January  7, 2002  4:05 PM

> >>I asked several Ada users (at least one of whom is here)
>
> Do we really have Ada users here? In my experience the answer is close to no
:0-)

I believe that I am the user to whom Randy is alluding.  He floated this idea
to me, and it looked appealing.  It is clear that there are difficulties, but
somehow I would like to give more consideration to the "implicit conversion"
idea.  But then I'm not sure if I qualify as an Ada user in Robert's view...
(Although I'd say that if there are no Ada users on the Ada Comment list, we
have a problem.)

>   x := To_String (b);
>
> or
>
>   x := Image (b);

Examples that don't have any context are not too convincing, one way or
another. Take a concrete example, that of Ada.Strings.Unbounded.  You typically
have to write something like:

    S := Ada.Strings.Unbounded.To_String ("hello");

This can be shortened somewhat with renamings or use clauses (but remember that
many people object to use clauses) but complicated expressions quickly become
unreadable.  For instance:

    package ASU renames Ada.Strings.Unbounded;

    Hello : constant array (Language) of ASU.Unbounded_String :=
        (English => ASU.To_String ("hello"),
         French => ASU.To_String ("bonjour"),
         ...
         Italian => ASU.To_String ("buongiorno"));

All these function calls are noise for the reader, much like explicit
conversions are in some other contexts.  For all practical purposes, a string
and an unbounded string are really similar abstraction, with a 1-to-1 mapping.
So I should be able to write:

    S := "hello";

    Hello : constant array (Language) of ASU.Unbounded_String :=
        (English => "hello", French => "bonjour", ..., Italian => "buongiorno");

This is considerably more readable.  Of course, it could be misused to produce
obfuscated programs, but many features of Ada have that property, so I cannot
get too excited.  What is important here is a good programmer is able to
produce a source text which is much easier to read.

****************************************************************

From: Robert Dewar
Sent: Monday, January  7, 2002  10:17 AM

Pascal, I am afraid you do not qualify as an Ada user :-)

If you are an Ada user, then so am I (I have written probably half a
million lines of commercially used code in Ada), but we are too contaminated
with our language lawyer hats :-)


In fact I think ada comment should NOT be used for general discussions o
ideas, but rather for submissions of ideas, and the discussions
should take place elsewhere, either on CLA for general chat, or on
the ARG list for serious language work.

There is a danger of comment becoming an Ada chit chat list, in which
case we will need to constitute another separate formal list for
language suggestions and comments on the standard.

****************************************************************

From: Arnaud Charlet
Sent: Monday, January  7, 2002  5:13 AM

> All these function calls are noise for the reader, much like explicit
> conversions are in some other contexts.  For all practical purposes, a string
> and an unbounded string are really similar abstraction, with a 1-to-1 mapping.
> So I should be able to write:
>
>     S := "hello";
>
>     Hello : constant array (Language) of ASU.Unbounded_String :=
>         (English => "hello", French => "bonjour", ..., Italian => "buongiorno");

You can already achieve a similar level of readability by overloading functions
"-" or "+", which would give you:

 Hello : constant array (Language) of ASU.Unbounded_String :=
     (English => -"hello", French => -"bonjour", ..., Italian => -"buongiorno");

Which is as readable as your version, and makes it clear that an operation
occurs.

****************************************************************

From: Pascal Leroy
Sent: Tuesday, January  8, 2002  3:13 AM

I have heard this argument many times before, but sorry, I don't buy it.
Readability is not only based on the number of characters it takes to write
something (otherwise C would be the most readable language on this planet ;-).
It is essential for the syntax of a construct to make it clear what the
underlying semantics are.  I don't see this in the above code fragment.

I think it's useful to discuss "-" and "+" separately.

I suspect that you chose "-" above because it is syntactically less obtrusive
than "+", but it is completely inappropriate here.  Your example is akin to
declaring a "+" operator with multiplicative semantics.  Unary "-" has the
intuitive meaning of 'complementarity' or 'negation'.  When I am reading the
above code fragment, I would expect the strings to be somehow 'negated'
(whatever that means).  So I would have to go to the specification of "-",
where hopefully I would find a big blinking comment saying "beware, this is
merely a conversion operation"; or worse, if the specification doesn't have
such a comment, I would have to look at the body of "-" to understand what
is going on. So much for readability!

The problem here is that the intent of the writer of the code is not at all
obvious to the reader, because of the poor choice of identifiers.

The case of "+" is different, because "+" conveys the meaning of an identity
function.  So yes, in Ada 95 this is a reasonable workaround, although it still
looks kludgy to me (you will notice for instance that the authors of the
predefined units, in their infinite wisdom, did not use this coding style, but
provided functions like To_String).  The question here is, why do I have to
write this silly + character?  What does it buy me?

> Which is as readable as your version, and makes it clear that an operation
> occurs.

I don't understand the fuss about "making it clear that an operation occurs".
We have many instances in Ada 95 where it is not explicit that an operation
occurs (controlled types, user-defined storage pool) and that's perfectly fine.
Once you trust that the abstraction you are using was written in a reasonable
way, you may assume that each assignment will do the right thing (e.g. in terms
of storage management) and concentrate on the meaning of the code you are
reading.  For this reason, controlled types (and others things) make Ada 95
more readable than Ada 83.  User-defined implicit conversions would play the
same role in the sense that they would remove clutter from client code.

****************************************************************

From: Arnaud Charlet
Sent: Tuesday, January 8, 2002  1:15 PM

> I think it's useful to discuss "-" and "+" separately.

It is interesting to note that if I remember correctly, adding a new
kind of operator that users could redefine to perform conversions was
discussed during the design of Ada 95, but the outcome was that since there
were already "-" and "+", it wasn't worthwhile. Now maybe things have
changed since then, that's possible.

> The question here is, why do I have to
> write this silly + character?  What does it buy me?

Or the question could be "does adding this new capability bring us
significantly, given that there are already reasonable (even if you will always
find arguments to disagree) options ? It is a matter of point of view, really.

Again, it would be nice to have the point of view of real Ada users here,
which we haven't got so far.

****************************************************************

From: Simon Wright
Sent: Monday, January 14, 2002  3:33 AM

> Again, it would be nice to have the point of view of real Ada users
> here, which we haven't got so far.

In our experience, untidy user-defined conversions occur most often
when trying to produce strings. So a user-defined 'Image would be
handy (no more than that):

  function My_Image (This : My_Type) return String;
  for My_Type'Image use My_Image;

No feeling either way on constructors.

--
Simon Wright                         Email: simon.j.wright@amsjv.com
Alenia Marconi Systems                     Voice: +44(0)23 9270 1778
Integrated Systems Division                  FAX: +44(0)23 9270 1800

****************************************************************


Questions? Ask the ACAA Technical Agent