Ada Introduction

by "Blag" - Senior Developer Evangelist

Return to Geeky Thursday

What is Ada?


Ada is a structured, statically typed, imperative, wide-spectrum and object-oriented high-level computer programming language, extended from Pascal and other languages.


It's was created for the United States Department of Defense.


Named after Ada Lovelace (1815-1852), the first computer programmer.


Compile-time checks and run-time checks prevent bugs, and nice pletora of errors related to memory.

How to install Ada?


On Linux it can be as easy as this...


sudo apt-get install gnat-4.9


sudo apt-get install gnat-gps


For other systems...you can simply check on Ada Compile/Install

Who uses Ada?


  • Department of Defense of the USA -> Lots of things
  • Wells-Fargo -> Real-time investment database system
  • Shell Oil -> Geophysical seismic processing system
  • Motorola -> Cellular phone switch testing system
  • Canadian Space Agency -> Satellite payload control system
  • Honeywell -> Airplane Information Management System (AIMS) for the Boeing 777

Starting out...


Because Ada uses compilation checks it doesn't have a REPL so we will need to use an editor to code...


If your're not using it already I will recommend you to get Geany, an awesome IDE that comes pre-configured for a lot of languages...Ada included...

Basic Concepts


Let's see the most basic example...a Hello World...


Create a new file and call it "hello.adb" (All in lowercase).


--Our first app in Ada

with Ada.Text_IO; use Ada.Text_IO;

procedure Hello is
begin
	Put ("Hello World!");
end Hello;

Compile time...


To compile and run our code, we need to press these 3 buttons in sequence...



If you're not using Geany...then follow this steps...


  • gcc -Wall -c "filename.adb"
  • gnatmake "filename"
  • "./filename"

If everything worked out fine...you should see this...


Variables


Variables need to have a type.


If their value doesn't change they need to be declared as constants.


Strings are very rigid...


Numeric values must be changed to string to be printed...


Create a new file and call it "variables.adb" (All in lowercase).


with Ada.Text_IO; use Ada.Text_IO;

procedure Variables is
    myString : constant String := "Hello World!";
    myName : String(1 .. 4);
    MyNumber : Natural;
begin
    Put_Line (myString);
    myName := "Blag";
    Put_Line ("Hello " & myName & "!");
    MyNumber := 37;
    Put_Line ("You are" & Integer'Image(myNumber) & " years old!");
end Variables;

Arrays


Arrays must be declared as a type that will be assigned to new variable.


Due to the constraints of the string type, we're going to create two arrays...one with Strings and the other with Unbounded Strings...


Arrays can't shrink or grow...


Create a new file and call it "arrays.adb" (All in lowercase).

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Arrays is
	type Arrays is array (1 .. 3) of String (1 .. 3);
	type UArrays is array (1 .. 3) of Unbounded_String;
	s1 : Unbounded_String;
	MyArray : Arrays;
	MyUArray : UArrays;
begin
	MyArray := ("ABC","123","XYZ");
	MyUArray := (s1 & "A",s1 & "ABC",s1 & "123");

	for i in Integer range 1..3 loop
		Put_Line(MyArray(i));
	end loop;
	Put_Line("");
	for i in Integer range 1..3 loop
		Put_Line(To_String(MyUArray(i)));
	end loop;	
end Arrays;

Multidimension Arrays


To create a multidimensional array, first we need to create an array type (Which is going to act as the rows)...


The we create another array type based on the first one (Which is going to act as the columns)...


Finally we create the variable of the type of the second array type...


Create a new file and call it "multiple_arrays.adb" (All in lowercase).

with Ada.Text_IO; use Ada.Text_IO;

procedure Multiple_Arrays is
	type rowsArrays is array (1 .. 3) of String (1 .. 1);
	type colsArrays is array (1 .. 2) of rowsArrays;
	MyArray : colsArrays;
begin
	MyArray(1)(1) := "A";
	MyArray(1)(2) := "B";
	MyArray(1)(3) := "C";
	MyArray(2)(1) := "1";
	MyArray(2)(2) := "2";
	MyArray(2)(3) := "3";

	for i in Integer range 1..2 loop
		for j in Integer range 1..3 loop
			Put_Line(MyArray(i)(j));
		end loop;
	end loop;
end Multiple_Arrays;

Maps

Maps are like dictionaries or hashed arrays...they can have a key and a value


The elements must be accessed using an Index...

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Ordered_Maps;

procedure Maps is
	package String_Maps is new 
                Ada.Containers.Indefinite_Ordered_Maps (Integer, String);
	use String_Maps;
	MyMap : Map;
	Index : Cursor;
begin
	MyMap.insert(1,"A");
	MyMap.insert(2,"B");
	MyMap.insert(3,"C");
	Index := MyMap.First;
	for i in Integer range 1..3 loop
		Put_Line(Integer'Image(Key(Index)) & " => " & Element(Index));
		Index := Next (Index);
	end loop;
end Maps;

Functions

Functions must be created inside a procedure...

They must always return a value...

The Return type must be set

with Ada.Text_IO; use Ada.Text_IO;

procedure Using_Functions is
	package Number_IO is new Ada.Text_IO.Integer_IO (Integer);
	num1 : Integer;
	num2 : Integer;
	
	function Sum(num1:Integer;num2:Integer) return Integer is
	begin
		return num1 + num2;
	end Sum;
	
begin
	Put("Enter a number: ");
	Number_IO.Get(num1);
	Put("Enter a number: ");
	Number_IO.Get(num2);
	Put("The sum is :" & Integer'Image(Sum(num1,num2)));
end Using_Functions;

Fibonacci List


Finally...we're going to make our first application...


Ok...we have made a lot of applications...but now this one makes sense -;)


Name your file "fibonacci.adb (all in lowercase)"


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Fibonacci is
	package Number_IO is new Ada.Text_IO.Integer_IO (Integer);
	num : Integer;
	
	function Fib(num:Integer;a:Integer;b:Integer) return Unbounded_String is
	result : Unbounded_String;
	begin
		if a > 0 and num > 1 then
			result := result & Integer'Image(a+b) & " " & Fib(num-1,a+b,a);
		elsif a = 0 then
			result := Integer'Image(a) & " " & Integer'Image(b) & " " & 
			          Integer'Image(a+b) & " " & Fib(num-1,a+b,b);
		end if;
		return result;
	end Fib;
begin
	Put("Enter a number: ");
	Number_IO.Get(num);
	Put(To_String(Fib(num,0,1)));
end Fibonacci;

When we run it we're going to see...

Making an LED Number App


This is one of my favorite codes of all time...


Name your file "LED_Numbers.lua"


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure LED_Numbers is
	package Number_IO is new Ada.Text_IO.Integer_IO (Integer);
	type Array_Row is array (1 .. 3) of Unbounded_String;
	type Array_Of_Array_Type is array (1 .. 10) of Array_Row;
	Array_Of_Arrays : Array_Of_Array_Type;
	s1 : Unbounded_String;
	s2 : Character;
	line1 : Unbounded_String;
	line2 : Unbounded_String;
	line3 : Unbounded_String;
	num : Integer;
	len : Natural;
	Array_Of_Arrays (1) (1) := s1 & " _  ";Array_Of_Arrays (1) (2) := S1 & "| | ";
	Array_Of_Arrays (1) (3) := S1 & "|_| ";Array_Of_Arrays (2) (1) := s1 & "  ";
	Array_Of_Arrays (2) (2) := S1 & "| ";Array_Of_Arrays (2) (3) := S1 & "| ";
	Array_Of_Arrays (3) (1) := s1 & " _  ";Array_Of_Arrays (3) (2) := S1 & " _| ";
	Array_Of_Arrays (3) (3) := S1 & "|_  ";Array_Of_Arrays (4) (1) := s1 & "_  ";
	Array_Of_Arrays (4) (2) := S1 & "_| ";Array_Of_Arrays (4) (3) := S1 & "_| ";
	Array_Of_Arrays (5) (1) := s1 & "    ";Array_Of_Arrays (5) (2) := S1 & "|_| ";
	Array_Of_Arrays (5) (3) := S1 & "  | ";Array_Of_Arrays (6) (1) := s1 & " _  ";
	Array_Of_Arrays (6) (2) := S1 & "|_  ";Array_Of_Arrays (6) (3) := S1 & " _| ";
	Array_Of_Arrays (7) (1) := s1 & " _  ";Array_Of_Arrays (7) (2) := S1 & "|_  ";
	Array_Of_Arrays (7) (3) := S1 & "|_| ";Array_Of_Arrays (8) (1) := s1 & "_   ";
	Array_Of_Arrays (8) (2) := S1 & " |  ";Array_Of_Arrays (8) (3) := S1 & " |  ";
	Array_Of_Arrays (9) (1) := s1 & " _  ";Array_Of_Arrays (9) (2) := S1 & "|_| ";
	Array_Of_Arrays (9) (3) := S1 & "|_| ";Array_Of_Arrays (10) (1) := s1 & " _  ";
	Array_Of_Arrays (10) (2) := S1 & "|_| ";Array_Of_Arrays (10) (3) := S1 & " _| ";
Put("Enter a number: ");
	Number_IO.Get(num);
	s1 := s1 & Integer'Image(num);
	len := Length(s1);
	for i in Integer range 2..len loop
		s2 := Element(s1,i);
		num := Character'Pos(s2) - 48;
		if num < 10 then
			num := num + 1;
		end if;
		line1 := line1 & Array_Of_Arrays (num) (1);
		line2 := line2 & Array_Of_Arrays (num) (2);
		line3 := line3 & Array_Of_Arrays (num) (3);
	end loop;
	Put(To_String(line1));
	Put_Line("");
	Put(To_String(line2));
	Put_Line("");
	Put(To_String(line3));
end LED_Numbers;

When we run it we're going to see...


Random Names


This App will generate 100,000 random names using two 16 elements arrays


We will measure the runtime


Name your file "random_names.abd (all in lowercase)"


with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Numerics.Discrete_Random;

procedure Random_Names is
	type Rand_Range is range 1..16;
	package Rand_Int is new Ada.Numerics.Discrete_Random(Rand_Range);
	type Arrays is array (1 .. 16) of Unbounded_String;
	type FullArray is array (1 .. 100000) of Unbounded_String;
	NameArray : Arrays;
	LastNameArray : Arrays;
	FullNameArray : FullArray;
	s1 : Unbounded_String;
	seed : Rand_Int.Generator;
	Num : Rand_Range;
begin
	NameArray := (s1 & "Anne",s1 & "Gigi",s1 & "Blag",s1 & "Juergen",
	              s1 & "Marek",s1 & "Ingo",s1 & "Lars",s1 & "Julia",
	              s1 & "Danielle",s1 & "Rocky",s1 & "Julien",s1 & "Uwe",
	              s1 & "Myles",s1 & "Mike",s1 & "Steven",s1 & "Fanny");
	LastNameArray := (s1 & "Hardy",s1 & "Read",s1 & "Tejada",s1 & "Schmerder",
	                  s1 & "Kowalkiewicz",s1 & "Sauerzapf",s1 & "Karg",s1 & "Satsuta",
	                  s1 & "Keene",s1 & "Ongkowidjojo",s1 & "Vayssiere",s1 & "Kylau",
	                  s1 & "Fenlon",s1 & "Flynn",s1 & "Taylor",s1 & "Tan");	              
	Rand_Int.Reset(seed);
	for i in Integer range 1..100000 loop
		Num := Rand_Int.Random(seed);
		FullNameArray(i) := NameArray(Rand_Range'Pos(Num)) & " " & 
                LastNameArray(Rand_Range'Pos(Num));
	end loop;
end Random_Names;

When we run it we're going to see...

How this behaves in Python?

And in Julia?

Decimal to Romans


This App will create a Roman Numeral based on a decimal number


This will include some nice commands...


Name your file "decimal_to_romans.adb" (all in lowercase)


with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Indefinite_Ordered_Maps;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; 
 
procedure Decimal_to_Romans is
	package String_Maps is new Ada.Containers.Indefinite_Ordered_Maps (Integer, String);
	package Number_IO is new Ada.Text_IO.Integer_IO (Integer);
	use String_Maps;
	Romans : Map;
	Index : Cursor;
	num : Integer;
	Result : Unbounded_String;
begin
	Romans.Insert (1000, "M"); Romans.Insert (900, "CM");
	Romans.Insert (500, "D"); Romans.Insert (400, "CD");
	Romans.Insert (100, "C"); Romans.Insert (90, "XC");
	Romans.Insert (50, "L"); Romans.Insert (40, "XL");
        Romans.Insert (10, "X"); Romans.Insert (9, "IX");
	Romans.Insert (5, "V"); Romans.Insert (4, "IV");
	Romans.Insert (1, "I");
   
	Put("Enter a number: ");
	Number_IO.Get(num);
	Index := Romans.Last;
	while num > 0 loop
		if num >= Key (Index) then
			Result := Result & Element (Index);
			num := num - Key (Index);
		else
			Index := Previous (Index);
		end if;
	end loop;
	Put(To_String(result));
end Decimal_to_Romans;

When we run it we're going to see...


Count Letters


In this example we're going to read a file and count how many time a letter appears...


Call your file "countletters.abd" (all in lowercase).


Create a file called "readme.txt" with the following text...


"This is a text file that we're going to read it using Ada"


with Ada.Text_IO;
with Ada.Containers.Indefinite_Ordered_Maps;

procedure CountLetters is
	package IO renames Ada.Text_IO;
	package String_Maps is new 
	Ada.Containers.Indefinite_Ordered_Maps (String, Integer);
	use String_Maps;
	Letters : Map;
	Line_Aux : String(1..1);
	Filename : constant String := "readme.txt";
	File : Ada.Text_IO.File_Type;
	Index : Cursor;
begin
	Ada.Text_IO.Open (File => File,Mode => Ada.Text_IO.In_File,Name => Filename);
	while not Ada.Text_IO.End_Of_File (File) loop
		declare
			Line : constant String := Ada.Text_IO.Get_Line (File);
		begin
			for i in Integer range 1..Line'Size / 8 loop	
				Line_Aux := "" & Line(i);
				Index := Letters.Find(Line_Aux);
				if Index = No_Element then
					Letters.insert(Line_Aux,1);
				else
					Letters(Line_Aux) := Letters(Line_Aux) + 1; 
				end if;
			end loop;
Index := Letters.First;
			loop
				IO.Put(Key(Index) & "-->" & Integer'Image(Element(Index)));
				IO.Put_Line("");
				Index := Next(Index);
				exit when Index = No_Element;
			end loop;
      end;
   end loop;
   IO.Close (File);
end CountLetters;

When we run it we're going to see...


That's it for now


Ada is a nice and interesting language


There's not so much information out there...but enough to get us started and going...



Contact Information


Blag --> blag@blagarts.com

@Blag on Twitter

Go back home...