Language Basics
Basic:
with Ada.Text_IO;
procedure Hello_World is
begin
Ada.Text_IO.Put("Hello World!");
end Hello_World;
Use:
with Ada.Text_IO; use Ada.Text_IO;
[...]
Put("Hello World!");
Good Ideas in Ada
Quiz:
double foo;
foo = 1 / 3;
Code:
int year, month, day, hour, minute, second;
Error:
day = minute;
Ada strong typing:
subtype Year_Type is Integer range 1582..4000;
subtype Month_Type is Integer range 1..12;
subtype Day_Type is Integer range 1..31;
subtype Hour_Type is Integer range 0..23;
subtype Minute_Type is Integer range 0..59;
subtype Second_Type is Integer range 0..59;
Year : Year_Type := 2001;
Month : Month_Type := 9;
Day : Day_Type := 19;
Hour : Hour_Type := 12;
Minute : Minute_Type := 0;
Second : Second_Type := 0;
Conversion:
day := Day_Type(Minute);
Exception handling:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Command_Line; use Ada.Command_Line;
with Ada.Numerics; use Ada.Numerics;
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
procedure Square_Root is
begin
if Argument_Count < 1 then
Put("Usage: ");
Put(Command_Name);
Put(" decimal");
Set_Exit_Status(Failure);
else
Put( Item => Sqrt(Float'Value(Argument(1))), Exp => 0);
Set_Exit_Status(Success);
end if;
exception
when Constraint_Error =>
Put(Command_Name);
Put(": cannot interpret numerical value from """);
Put(Argument(1));
Put("""");
Set_Exit_Status(Failure);
when Argument_Error =>
Put(Command_Name);
Put(": cannot take square root of ");
Put(Argument(1));
Set_Exit_Status(Failure);
end Square_Root;
C++ try/catch
try {
if (atof(argv[1]) < 0)
throw 1;
cout << sqrt(argv[1]);
}
catch (int e) {
if (e == 1)
cout << "square root of a negative\n";
}
C++ Default Values
int Tax_Amount(int income; int exemptions = 1; bool blind = false;)
Tax_Amount(10); // okay
Tax_Amount(10, 2); // okay
Tax_Amount(10, true); // illegal
Similar:
function Tax_Amount (Income : Integer;
Exemptions : Integer := 1;
Blind : Boolean := False;) is [...]
And then call it like this:
foo := Tax_Amount(Income => 10, Blind => True);
And, if you name the parameters, you can put them in any order at all:
foo := Tax_Amount(Blind => True, Income => 10);
Curses:
C/C++:
move(y,x);
addch(c);
mvaddch(y, x, c);
mvwaddch(win, y, x, c);
Ada overloading and defaults:
procedure Add (Win : in Window := Standard_Window;
Ch : in Character)
is
and
procedure Add (Win : in Window := Standard_Window;
Line : in Line_Position;
Column : in Column_Position;
Ch : in Character)
is
Calling with names:
Add(Column => 0, Line => 2, Ch => 'b');
mvaddch(0, 2, 'b');
Three common errors:
Null loops:
while (c > 0);
c--;
Explicitly in Ada:
while c > 0 loop
null;
end loop;
Dangling Else:
if (a > b) if a > b then
if (c > d) if c > d then
foo = 0; foo := 0;
else end if;
foo = 1; else
foo := 1;
end if;
Assignment in a condition:
if (a = 1)
b = -1;
In Java:
if (a = true)
b = -1;
In Ada, it's an error:
if a := true then
b = -1;
Convenience:
while (X = numleft()) {
cout << X << " left to work on" << endl;
process_one();
}
Ada version if right:
loop x := NumLeft;
X := NumLeft; while x > 0 loop
exit when X = 0; put(X);
put(X); put(" left to work on");
put(" left to work on"); new_line;
new_line; process_one;
process_one; x := NumLeft;
end loop; end loop;
Ada version if wrong:
loop while x = NumLeft loop
exit when X /= NumLeft; put(X);
put(X); put(" left to work on");
put(" left to work on"); new_line;
new_line; process_one;
process_one; end loop;
end loop;
Case and Fallthrough:
switch (b) { case b is
case 'a': do_this(); break; when 'a' => do_this;
case 'b': do_that(); break; when 'b' => do_that;
} when others => null;
end case;
Special syntax for multiple cases:
switch(b) { case b is
case 'A': when 'A' | 'a' => do_this;
case 'a': when 'B' | 'b' => do_that;
do_this(); when others => null;
break; end case;
case 'B':
case 'b':
do_that();
break;
}
Templates / Generics
#include <iostream> with Ada.Integer_Text_IO;
using namespace std; use Ada.Integer_Text_IO
template <class T> procedure Generic_Swap is
void exchange ( T & x, T & y ) { generic
T z = x; type Item is private;
x = y; procedure Exchange(X, Y: in out Item);
y = z; procedure Exchange(X, Y: in out Item) is
} Temp: Item;
begin
int main ( ) { Temp := X;
int a = 5, b = 10; X := Y;
Y := Temp;
exchange ( a, b ); end;
cout << a << " " << b << endl;
A, B : Integer;
return 0; procedure Swap is new Exchange(integer);
} begin
A := 1;
B := 2;
Swap(A,B);
put(A); put(" "); put(B); new_line;
end Generic_Swap;
Unset out parameters:
procedure Foo (x: in integer; y: out integer) is
z: integer;
begin
z := x + y;
end foo;
[...]
bar := 2;
foo(1, bar);
Can't use in parameter:
procedure Foo (x: in integer; y: out integer) is
begin
X := 2;
end foo;
Built-In Features
Float'Succ(Coolant_Temp);
Numerical type attributes:
'Succ
'Pred
'Value
'Image
'Min
'Max
Programmer defined:
type Tone_Type is (Low_Do, Re, Me, Fa, So, La, Ti, High_Do);
Tone : Tone_Type;
[...]
Ada.Text_IO.Put (Tone_Type'Image(Tone)); -- Print as string
Tone := Tone_Type'Succ(Tone); -- up one note
Precise variables specifications:
type Measurement_Type is delta 0.0000000001 digits 20;
Ada Problems
Incorrect string assignment if different length:
Name := "Bob";
Bounded Strings:
with Ada.Strings.Bounded;
use Ada.Strings.Bounded;
package Bounded_80 is
new Generic_Bounded_Length(80);
use Bounded_80;
B : Bounded_String;
B := To_Bounded_String("Bob");
Text_IO.Put_Line( To_String(B) );
Unbounded string:
with Ada.Strings.Unbounded;
use Ada.Strings.Unbounded;
U : Unbounded_String;
U := To_Unbounded_String("Bob");
Text_IO.Put_Line( To_String(U) );
You can dodge some this by using `rename':
function To_U_Str (Source: String) return Unbounded_String
renames Ada.Strings.Unbounded.To_Unbounded_String;
function Reg_Str (Source: Unbounded_String) return String
renames Ada.Strings.Unbounded.To_String;
[...]
U := To_U_Str("Bob");