4.5.7 Conditional Expressions
Language Design Principles
{
AI05-0147-1}
The rules for
conditional_expressions
have been designed as much as possible to work similarly to a parenthesized
expression. The intent is that as much as possible, wherever a parenthesized
expression would be allowed, a
conditional_expression
would be allowed, and it should work the same way.
Syntax
Discussion: {
AI05-0147-1}
The syntactic category
conditional_expression
appears only as a primary that is parenthesized. The above rule allows
it to additionally be used in other contexts where it would be directly
surrounded by parentheses.
The grammar makes
the following directly legal:
A := (if X then Y else Z); -- parentheses required
A := B + (if X then Y else Z) + C; -- parentheses required
The following
procedure calls are syntactically legal; the first uses the above rule
to eliminate the redundant parentheses found in the second:
P(if X then Y else Z);
P((if X then Y else Z)); -- redundant parentheses
P((if X then Y else Z), Some_Other_Param);
P(Some_Other_Param, (if X then Y else Z));
P(Formal => (if X then Y else Z));
whereas the following
are illegal:
P(if X then Y else Z, Some_Other_Param);
P(Some_Other_Param, if X then Y else Z);
P(Formal => if X then Y else Z);
because in these latter cases, the
conditional_expression
is not immediately surrounded by parentheses (which means on both sides!).
The English-language rule applies in all places
that could surround an expression with parentheses, including pragma
arguments, type conversion and qualified expression operands, and array
index expressions.
This English-language rule could have been implemented
instead by adding a nonterminal
expression_within_parentheses,
which would consist of
expressions
and
conditional_expressions.
Then, that could be used in all of the syntax which could consist of
parens directly around an
expression.
We did not do that because of the large amount of change required. A
complete grammar is given in
AI05-0147-1.
Name Resolution Rules
Reason: This
rule distributes an enclosing type conversion to the
dependent_expressions.
This means that
T(if C then A else B)
has the same semantics
as
(if C then T(A) else T(B))
Reason: This rule supports the use of
numeric literals and universal expressions within a
conditional_expression.
Ramification: If the type of the
conditional_expression
cannot be determined by one of these rules, then Name Resolution has
failed for that expression, even if the
dependent_expressions
would resolve individually.
Legality Rules
Reason: The
exemption for a case expression that occurs in an instance allows the
following example:
generic
with function Int_Func return Integer;
package G is
X : Float := (case Int_Func is
when Integer'First .. -1 => -1.0,
when 0 => 0.0,
when Positive => 1.0);
end G;
function Nat_Func return Natural is (123);
package I is new G (Int_Func => Nat_Func); -- Legal
Note that the Legality Rules still apply in
the generic unit itself; they are just not enforced in an instance of
the unit.
Dynamic Semantics
Ramification: Else is required
unless the
if_expression
has a boolean type, so the last sentence can only apply to
if_expressions
with a boolean type.
Examples
{
AI12-0312-1}
Put_Line ("Casey is " &
(
if Casey.Sex = M
then "Male"
else "Female")); --
see 3.10.1
{
AI12-0312-1}
function Card_Color (Card : Suit)
return Color
is --
see 3.5.1
(
case Card
is
when Clubs | Spades => Black,
when Hearts | Diamonds => Red);
Extensions to Ada 2005
{
AI05-0147-1}
If expressions and case expressions are new.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe