Why are if expressions and if statements in ada, also for case

Taken from Introduction to Ada—If expressions:

Ada's if expressions are similar to if statements. However, there are a few differences that stem from the fact that it is an expression:

All branches' expressions must be of the same type

It must be surrounded by parentheses if the surrounding expression does not already contain them

An else branch is mandatory unless the expression following then has a Boolean value. In that case an else branch is optional and, if not present, defaults to else True.

I do not understand the need to have two different ways of constructing code with the if keyword. What is the reasoning behind this?

Also there case expressions and case statements. Why is this?

4 Answers

I think this is best answered by quoting the Ada 2012 Rationale Chapter 3.1:

One of the key areas identified by the WG9 guidance document [1] as needing attention was improving the ability to write and enforce contracts. These were discussed in detail in the previous chapter. When defining the new aspects for preconditions, postconditions, type invariants and subtype predicates it became clear that without more flexible forms of expressions, many functions would need to be introduced because in all cases the aspect was given by an expression. However, declaring a function and thus giving the detail of the condition, invariant or predicate in the function body makes the detail of the contract rather remote for the human reader. Information hiding is usually a good thing but in this case, it just introduces obscurity. Four forms are introduced, namely, if expressions, case expressions, quantified expressions and expression functions. Together they give Ada some of the flexible feel of a functional language.

In addition, if statements and case statements often assigns different values to the same variable in all branches, and nothing else:

if Foo > 10 then Bar := 1; else Bar := 2; end if; 

In this case, an if expression may increase readability and more clearly state in the code what's going on:

Bar := (if Foo > 10 then 1 else 2); 

We can now see that there's no longer a need for the maintainer of the code to read a whole if statement in order to see that only a single variable is updated.

Same goes for case expressions, which can also reduce the need for nesting if expressions.

Also, I can throw the question back to you: Why does C-based languages have the ternary operator ?: in addition to if statements?

1

Egilhh already covered the main reason, but there are sometimes other useful reasons to implement expressions. Sometimes you make packages where only one or two methods are needed and they are the only reason to make a package body. You can use expressions to make expression functions which allow you to define the operations in the spec file.

Additionally, if you ever end up with some complex variant record combinations, sometimes expressions can be used to setup default values for them in instances where you normally would not be able to as cleanly. Consider the following example:

with Ada.Text_IO; use Ada.Text_IO; procedure Hello is type Binary_Type is (On, Off); type Inner(Binary : Binary_Type := Off) is record case Binary is when On => Value : Integer := 0; when Off => null; end case; end record; type Outer(Some_Flag : Boolean) is record Other : Integer := 32; Thing : Inner := (if Some_Flag then (Binary => Off) else (Binary => On, Value => 23)); end record; begin Put_Line("Hello, world!"); end Hello; 

I had something come up with a more complex setup that was meant to map to a complex messaging interface at the hardware level. It's nice to have defaults whenever possible. Now I cold have used a case inside of Outer, but then I would have had to come up with two separately named versions of the message field for each case, which really isn't optimal when you want your code to map to an ICD. Again, I could have used a function to initialize it as well, but as noted in the other posters answer, that isn't always a good way to go.

Another place that outlines the motivation for adding conditional expressions to Ada can be found in the ARG document, AI05-0147-1, which explains the motivation and gives some examples of use.

An example of a place where I find them quite useful is in processing command line parameters, for the case when a default value is used if the parameter is not specified on the command line. Generally, you'd want to declare such values as constants in one's program. Conditional expressions makes it easier to do that.

with Ada.Command_Line; use Ada; procedure Main is N : constant Positive := (if Command_Line.Argument_Count = 0 then 2_000_000 else Positive'Value (Command_Line.Argument (1))); ... 

Otherwise, without conditional expressions, in order to achieve the same effect you'd need to declare a function, which I find to be more difficult to read;

with Ada.Command_Line; use Ada; procedure Main is function Get_N return Positive is begin if Command_Line.Argument_Count = 0 then return 2_000_000; else return Positive'Value (Command_Line.Argument (1)); end if; end Get_N; N : constant Positive := Get_N; ... 

The if expression in Ada feels and works a lot like a statement using the ternary operator in the C-based languages. I took the liberty of copying some code from learn.adacore.com that introduces the if expression:

with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure Check_Positive is N : Integer; begin Put ("Enter an integer value: "); Get (N); Put (N,0); declare S : constant String := (if N > 0 then " is a positive number" else " is not a positive number"); begin Put_Line (S); end; end Check_Positive; 

And I translated it to a C-based language - in this case, Java. I believe the main point to notice is that both languages, although syntactically different, are effectively doing the same thing: testing a condition and assigning one of two values to a variable all within one statement. Although I realize this is an oversimplification for most here on stackoverlfow. My goal is to help the beginner to understand the basic concept with introductory examples. Cheers.

import java.util.Scanner; public class IfExpression { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter an integer value: "); var N = in.nextInt(); System.out.print(N); var S = N > 0 ? " is a positive number" : " is not a positive number"; System.out.println(S); in.close(); } } 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like