Version 1.4 of ai12s/ai12-0037-1.txt
!standard A.19(4/3) 12-12-28 AI12-0037-1/02
!class binding interpretation 12-11-29
!status Amendment 202x 12-12-28
!status ARG Approved 7-0-3 12-12-07
!status work item 12-11-29
!status received 12-08-06
!priority Low
!difficulty Easy
!subject New types in Ada.Locales can't be converted to/from strings
!summary
Types Ada.Locales.Language_Code and Ada.Locales.Country_Code should be derived
from type String.
!question
It is difficult to output objects of type Ada.Locales.Language_Code
or Ada.Locales.Country_Code; you can't give them to Text_IO.Put
because their type isn't String, but you also
can't convert them to String because they run afoul of 4.6(24.5/2)
which requires that component subtypes must statically match.
Should some change be made in order to make this easier? (Yes.)
!recommendation
(See summary.)
!wording
Replace A.19(4/3) with:
type Language_Code is new String(1 .. 3)
with Dynamic_Predicate => (for all E of Language_Code => E in 'a' .. 'z');
type Country_Code is new String(1 .. 2)
with Dynamic_Predicate => (for all E of Country_Code => E in 'A' .. 'Z');
Add an AARM note following:
These types are declared as derived from type String so that they can easily be
converted to or from type String. That's important if one of these values needs to be
input or displayed (via Text_IO, perhaps). We use the predicate to ensure that only
possible component values are used. Ada does not allow converting between
unrelated types with components that don't statically match, so We cannot declare
new types with constrained components if we want conversions to or from type String.
!discussion
The use of a predicate rather than constrained component subtypes means that this
change is inconsistent with the original Ada 2012 definition - the exception raised
on failure is changed. We don't consider that important as it is unlikely that users
will construct these values and when they do, it is highly unlikely that they would
handle any resulting exception (which would represent a bug).
We could have used a raise_expression as described in AI12-0022-1 to avoid this
inconsistency, but the exception raised wasn't considered important enough to use
the extra machinery. (We also avoid the problem addressed by AI12-0054-1 by using
this formulation; any technique for raising Constraint_Error would suffer from
that problem.)
The predicate could have been written in a number of other ways; this one doesn't
depend explicitly on the bounds of the subtypes, so it is preferred. Of course, an
implementation can replace this by anything equivalent if that will provide better
performance.
!corrigendum A.19(4/3)
Replace the paragraph:
type Language_Code is array (1 .. 3) of Character range 'a' .. 'z';
type Country_Code is array (1 .. 2) of Character range 'A' .. 'Z';
by:
type Language_Code is new String (1 .. 3)
with Dynamic_Predicate => (for all E of Language_Code => E in 'a' .. 'z');
type Country_Code is new String (1 .. 2)
with Dynamic_Predicate => (for all E of Country_Code => E in 'A' .. 'Z');
!ACATS test
An ACATS C-Test should be created to test that Language_Codes and Country_Codes can be
converted to type String for output via Put_Line.
!appendix
!topic New types in Ada.Locales can't be converted to/from strings
!reference A.19
!from Adam Beneschan 12-08-06
!discussion
It was just pointed out on comp.lang.ada that it is difficult to
output objects of type Language_Code or Country_Code; you can't give
them to Text_IO.Put because their type isn't String, but you also
can't convert them to String because they run afoul of 4.6(24.5/2)
which requires that component subtypes must statically match.
Assuming that it's desirable to keep the range constraint on the
component subtype, I'd suggest adding To_String and From_String
functions to Ada.Locales:
function To_String (C : Language_Code) return String;
function To_String (C : Country_Code) return String;
function From_String (S : String) return Language_Code;
function From_String (S : String) return Country_Code;
with From_String raising Constraint_Error if S has the wrong length or
any character in S is out of range.
****************************************************************
From: Randy Brukardt
Sent: Thursday, August 9, 2012 6:08 PM
That's the "easy" solution, but it seems very, very strange that you
can't do these conversions directly (surely you would expect to be able
to do so).
I'd suggest changing to a rule where the component types still have to
be the same, but the constraints get rechecked (possibly requiring a
loop). That would not require making a copy of the array (other than
in cases where it is already required to do so, that is, when the component
sizes are different), but would give more flexibility for cases like this.
Alternatively, we could only require convertability for elementary types
(I'd be dubious of expanding that for composite types), and let copies be
required sometimes. (Compilers probably already can make such copies,
because of the component size difference cases.)
****************************************************************
Editor's note: This solution was suggested by Bob Duff in private mail.
He deserves credit (or blame!) for this clever idea.
****************************************************************
Questions? Ask the ACAA Technical Agent