Statements, Declarations, and Control Structures

Statements and Declarations

The following code samples are all equivalent, and illustrate the use of comments and working with integer variables:

[Ada]

--
--  Ada program to declare and modify Integers
--
procedure Main is
   --  Variable declarations
   A, B : Integer := 0;
   C    : Integer := 100;
   D    : Integer;
begin
   --  Ada uses a regular assignment statement for incrementation.
   A := A + 1;

   --  Regular addition
   D := A + B + C;
end Main;

[C++]

/*
 *  C++ program to declare and modify ints
 */
int main(int argc, const char* argv[]) {
   //  Variable declarations
   int a = 0, b = 0, c = 100, d;

   //  C++ shorthand for incrementation
   a++;

   //  Regular addition
   d = a + b + c;
}

[Java]

/*
 *  Java program to declare and modify ints
 */
public class Main {
   public static void main(String [] argv) {
      //  Variable declarations
      int a = 0, b = 0, c = 100, d;

      //  Java shorthand for incrementation
      a++;

      //  Regular addition
      d = a + b + c;
   }
}

Statements are terminated by semicolons in all three languages. In Ada, blocks of code are surrounded by the reserved words begin and end rather than by curly braces. We can use both multi-line and single-line comment styles in the C++ and Java code, and only single-line comments in the Ada code.

Ada requires variable declarations to be made in a specific area called the declarative part, seen here before the begin keyword. Variable declarations start with the identifier in Ada, as opposed to starting with the type as in C++ and Java (also note Ada's use of the : separator). Specifying initializers is different as well: in Ada an initialization expression can apply to multiple variables (but will be evaluated separately for each), whereas in C++ and Java each variable is initialized individually. In all three languages, if you use a function as an initializer and that function returns different values on every invocation, each variable will get initialized to a different value.

Let's move on to the imperative statements. Ada does not provide ++ or -- shorthand expressions for increment/decrement operations; it is necessary to use a full assignment statement. The := symbol is used in Ada to perform value assignment. Unlike C++'s and Java's = symbol, := can not be used as part of an expression. So, a statement like A := B := C; doesn't make sense to an Ada compiler, and neither does a clause like "if A := B then ...." Both are compile-time errors.

You can nest a block of code within an outer block if you want to create an inner scope:

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
begin
   Put_Line ("Before the inner block");

   declare
      Alpha : Integer := 0;
   begin
      Alpha := Alpha + 1;
      Put_Line ("Now inside the inner block");
   end;

   Put_Line ("After the inner block");
end Main;

It is OK to have an empty declarative part or to omit the declarative part entirely---just start the inner block with begin if you have no declarations to make. However it is not OK to have an empty sequence of statements. You must at least provide a null; statement, which does nothing and indicates that the omission of statements is intentional.

Conditions

The use of the if statement:

[Ada]

if Variable > 0 then
   Put_Line (" > 0 ");
elsif Variable < 0 then
   Put_Line (" < 0 ");
else
   Put_Line (" = 0 ");
end if;

[C++]

if (Variable > 0)
   cout << " > 0 " << endl;
else if (Variable < 0)
   cout << " < 0 " << endl;
else
   cout << " = 0 " << endl;

[Java]

if (Variable > 0)
   System.out.println (" > 0 ");
else if (Variable < 0)
   System.out.println (" < 0 ");
else
   System.out.println (" = 0 ");

In Ada, everything that appears between the if and then keywords is the conditional expression---no parentheses required. Comparison operators are the same, except for equality (=) and inequality (/=). The english words not, and, and or replace the symbols !, &, and |, respectively, for performing boolean operations.

It's more customary to use && and || in C++ and Java than & and | when writing boolean expressions. The difference is that && and || are short-circuit operators, which evaluate terms only as necessary, and & and | will unconditionally evaluate all terms. In Ada, and and or will evaluate all terms; and then and or else direct the compiler to employ short circuit evaluation.

Here are what switch/case statements look like:

[Ada]

case Variable is
   when 0 =>
      Put_Line ("Zero");
   when 1 .. 9 =>
      Put_Line ("Positive Digit");
   when 10 | 12 | 14 | 16 | 18 =>
      Put_Line ("Even Number between 10 and 18");
   when others =>
      Put_Line ("Something else");
end case;

[C++]

switch (Variable) {
   case 0:
      cout << "Zero" << endl;
      break;
   case 1: case 2: case 3: case 4: case 5:
   case 6: case 7: case 8: case 9:
      cout << "Positive Digit" << endl;
      break;
   case 10: case 12: case 14: case 16: case 18:
      cout << "Even Number between 10 and 18" << endl;
      break;
   default:
      cout << "Something else";
}

[Java]

switch (Variable) {
   case 0:
      System.out.println ("Zero");
      break;
   case 1: case 2: case 3: case 4: case 5:
   case 6: case 7: case 8: case 9:
      System.out.println ("Positive Digit");
      break;
   case 10: case 12: case 14: case 16: case 18:
      System.out.println ("Even Number between 10 and 18");
      break;
   default:
      System.out.println ("Something else");
}

In Ada, the case and end case lines surround the whole case statement, and each case starts with when. So, when programming in Ada, replace switch with case, and replace case with when.

Case statements in Ada require the use of discrete types (integers or enumeration types), and require all possible cases to be covered by when statements. If not all the cases are handled, or if duplicate cases exist, the program will not compile. The default case, default: in C++ and Java, can be specified using when others => in Ada.

In Ada, the break instruction is implicit and program execution will never fall through to subsequent cases. In order to combine cases, you can specify ranges using .. and enumerate disjoint values using | which neatly replaces the multiple case statements seen in the C++ and Java versions.

Loops

In Ada, loops always start with the loop reserved word and end with end loop. To leave the loop, use exit---the C++ and Java equivalent being break. This statement can specify a terminating condition using the exit when syntax. The loop opening the block can be preceded by a while or a for.

The while loop is the simplest one, and is very similar across all three languages:

[Ada]

while Variable < 10_000 loop
   Variable := Variable * 2;
end loop;

[C++]

while (Variable < 10000) {
   Variable = Variable * 2;
}

[Java]

while (Variable < 10000) {
    Variable = Variable * 2;
}

Ada's for loop, however, is quite different from that in C++ and Java. It always increments or decrements a loop index within a discrete range. The loop index (or "loop parameter" in Ada parlance) is local to the scope of the loop and is implicitly incremented or decremented at each iteration of the loop statements; the program cannot directly modify its value. The type of the loop parameter is derived from the range. The range is always given in ascending order even if the loop iterates in descending order. If the starting bound is greater than the ending bound, the interval is considered to be empty and the loop contents will not be executed. To specify a loop iteration in decreasing order, use the reverse reserved word. Here are examples of loops going in both directions:

[Ada]

--  Outputs 0, 1, 2, ..., 9
for Variable in 0 .. 9 loop
   Put_Line (Integer'Image (Variable));
end loop;

--  Outputs 9, 8, 7, ..., 0
for Variable in reverse 0 .. 9 loop
   Put_Line (Integer'Image (Variable));
end loop;

[C++]

//  Outputs 0, 1, 2, ..., 9
for (int Variable = 0; Variable <= 9; Variable++) {
   cout << Variable << endl;
}

//  Outputs 9, 8, 7, ..., 0
for (int Variable = 9; Variable >=0; Variable--) {
   cout << Variable << endl;
}

[Java]

//  Outputs 0, 1, 2, ..., 9
for (int Variable = 0; Variable <= 9; Variable++) {
   System.out.println (Variable);
}

//  Outputs 9, 8, 7, ..., 0
for (int Variable = 9; Variable >= 0; Variable--) {
   System.out.println (Variable);
}

Ada uses the Integer type's 'Image attribute to convert a numerical value to a String. There is no implicit conversion between Integer and String as there is in C++ and Java. We'll have a more in-depth look at such attributes later on.

It's easy to express iteration over the contents of a container (for instance, an array, a list, or a map) in Ada and Java. For example, assuming that Int_List is defined as an array of Integer values, you can use:

[Ada]

for I of Int_List loop
   Put_Line (Integer'Image (I));
end loop;

[Java]

for (int i : Int_List) {
   System.out.println (i);
}