❌ About FreshRSS

Reading view

There are new articles available, click to refresh the page.

The problem with π (iv) – Fortran to Ada

The Fortran program can also be translated to Ada. Below is the Ada program. It contains some code to output the resulting value of pi to the text file piCalc1000ADA.txt. In this code a is a “dynamic” array of integers, which is allocated using a declare block. In reality a is just of type pia, declared at a later point in the program.

with ada.Text_IO; use Ada.Text_IO;
with ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with ada.strings.unbounded; use ada.strings.unbounded;
with ada.strings.unbounded.Text_IO; use ada.strings.unbounded.Text_IO;

procedure piSpigotDYN is

    n, len : integer;
    q, x, nines, predigit : integer;
    type pia is array(integer range <>) of integer;
    infp : file_type;

begin
    create(infp,out_file,"piCalc1000ADA.txt");
    n := 1000;
    len := 10 * n / 3;

    declare
       a : pia(1..len);
    begin

    a := (1..len => 2);
    nines := 0;
    predigit := 0;

    for j in 1..n loop
       q := 0;
       for i in reverse 1..len loop
          x := 10 * a(i) + q * i;
          a(i) := x mod (2*i-1);
          q := x / (2*i-1);
       end loop;
       a(1) := q mod 10;
       q := q / 10;
       if q = 9 then
          nines := nines + 1;
       elsif q = 10 then
          put(infp,predigit+1,width=>1);
          for k in 1..nines loop
             put(infp,0,width=>1);
          end loop;
          predigit := 0;
          nines := 0;
       else
          put(infp,predigit,width=>1);
          predigit := q;
          if nines /= 0 then
             for k in 1..nines loop
                put(infp,9,width=>1);
                nines := 0;
             end loop;
          end if;
       end if;
    end loop;
    put(infp,predigit,width=>1);

    close(infp);
    end;
end piSpigotDYN;

The problem with π (iii) – Pascal to Fortran

A while back I posted on the Spigot algorithm in Pascal (and C) for calculating the first 1000 decimal places of π. Now converting it to Fortran is quite easy.

program piSpigot

   integer :: n, len
   integer :: i, j, k, q, x, nines, predigit
   integer, dimension(3500) :: a

   n = 1000
   len = (10 * n) / 3

   a = 2
   nines = 0
   predigit = 0
   999 format(I1)

   do j = 1,n
      q = 0
      do i = len,1,-1
         x = 10 * a(i) + q * i
         a(i) = mod(x,2*i-1)
         q = x / (2*i-1)
      end do
      a(1) = mod(q,10)
      q = q / 10
      if (q == 9) then
         nines = nines + 1
      elseif (q == 10) then
         write(*,999,advance='no') predigit+1
         do k = 1, nines
            write(*,999,advance='no') 0
         end do
         predigit = 0
         nines = 0
      else
         write(*,999,advance='no') predigit
         predigit = q
         if (nines /= 0) then
            do k = 1,nines
               write(*,999,advance='no') 9
               nines = 0
            end do
         end if
      end if
   end do
   write(*,999,advance='no') predigit

end program piSpigot

This algorithm is good, but it could be improved upon by making the array dynamic. All that really involves is reworking some code at the top of the program. In the snippet of code below, the array a is made allocatable (Line 5), I/O is added to prompt for the number of decimal points required to be calculated, and then on Line 11 the space for a is allocated. At the end of the program, the memory is deallocated.

program piSpigot

   integer :: n, len
   integer :: i, j, k, q, x, nines, predigit
   integer, dimension(:), allocatable :: a

   write(*,*) 'Number of decimal points? '
   read(*,*) n
   len = (10 * n) / 3

   allocate(a(len))
   ...
   deallocate(a)
end program piSpigot

Why does Ada Language use Semicolon `;` to Separate Parameters in Subprogram Declarations?

fellow coders..

I'm just a new learner and try to practice some programming paradigms in their specific designed environments. Recently I've learn quite many new small things in Procedural Programming in Ada Language and have a great experience of learning. But, I cannot find the answer by myself for the wonder why Ada does use Semicolons ; to separate Parameters in Subprogram Declarations.

-- subprogram declaration - - - - - - - - -

procedure Initialize_Some_Things
   ( Result : out Integer
   ; Asset : in Integer
   ; Option: in Integer ) is
begin
   null;
end Initialize_Some_Things;

-- invoking subprogram - - - - - - - - -

Instance : Integer := 0;
Initialize_Some_Things (Instance, 9, 5);

It's obviously strange for anyone who comes from any other programming language to use a Semicolon to Separate Parameters in Subprogram Declaration though. And it's even more strange when the Invocations of Subprograms require to use Comma , instead of Semicolon ; as in Declarations. I've searched for related questions for sometime and find nothing on the Google. Is there anyway to submit a request to make this subtle change to the standard specification of the language?

I've found no related question on Google. And I hope I can find here.

Programming made easy – nested loops

We’re not quite done with loops yet. There are still a few things to learn, although some can be left for later. There are certain situations where it is appropriate to use a loop inside another loop. Such a loop is called a nested loop. A nested loop is executed, essentially, from the inside out. Each loop is like a layer and has its own loop control, its own condition and its own loop body. Below is a schematic of three nested loops.

A loop inside a loop, inside a loop.

There are many different kinds of nested loops, and they are largely dependent on the underlying algorithm. Below are some examples of the types of nested loops that are possible.

Various examples of nested loops

We will consider how a nested loop can be used to create a times table. It basically works by iterating the inner loop 12 times for every iteration of the outer loop. So, 12 × 12 = 144 iterations. The outer loop is highlighted in blue, and the inner loop in red. Here is a sample output:

 1   2   3   4   5   6   7   8   9  10  11  12
 2   4   6   8  10  12  14  16  18  20  22  24
 3   6   9  12  15  18  21  24  27  30  33  36
 4   8  12  16  20  24  28  32  36  40  44  48
 5  10  15  20  25  30  35  40  45  50  55  60
 6  12  18  24  30  36  42  48  54  60  66  72
 7  14  21  28  35  42  49  56  63  70  77  84
 8  16  24  32  40  48  56  64  72  80  88  96
 9  18  27  36  45  54  63  72  81  90  99 108
10  20  30  40  50  60  70  80  90 100 110 120
11  22  33  44  55  66  77  88  99 110 121 132
12  24  36  48  60  72  84  96 108 120 132 144

Ada

with ada.Text_IO; use Ada.Text_IO;
with ada.Integer_Text_IO; use ada.Integer_Text_IO;
procedure nested is 
begin
   for x in 1..12 loop
      for y in 1..12 loop
         put(x*y, width=>4);
      end loop;
      new_line;
   end loop;
end nested;

Fortran

program nested
   integer :: x, y
   do x = 1, 12
      do y = 1, 12
         write(*,10,advance='no') xy
         10 format(I4)
      end do
      write(*,*)
   end do
end program nested

C

#include <stdio.h>
int main(void){
   int x, y;
   for (x=1; x<=12; x=x+1)
   {
      for (y=1; y<=12; y=y+1)
         printf("%4d", x*y);
      printf("\n");
   }
   return 0;
}

Julia

for x = 1:12
   for y = 1:12
      @printf("%4d", x*y)
   end
   println()
end
println(h)

spqr

Programming made easy – loops (iii)

There are of course other loops. These loops are normally used when the number of times a loop iterates isn’t known. These type of loops generally use some form of condition to control the loop. The most prominent type of loop is the while loop. A while loop checks a condition, and if true, processes the code in the loop body, otherwise it exists the loop. Unlike the for loop, which controls the values of the loop index in terms of updating its value, in the loops like while, this process must be added, i.e. the value of i is given the value 1, before the loop is activated, and its value is incremented within the loop body.

We will consider some of these loops using the same Harmonic series, this time in increasing order. The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.

Fortran

program harmonic
   integer :: n, i
   real :: h

   read (*,*) n
   h = 0
   i = 1
   do while (i <= n)
      h = h + 1.0/i
      i = i + 1
   end do
   write(*,*) h
end program harmonic

Here the index variable, i, must be initiated to the value 1 before the loop begins, and incremented within the loop. The condition states that the loop continues while the value of i is less than or equal to n, i.e. (i <= n) . Fortran also provides a more generic do/end do loop.

C

#include <stdio.h>

int main(void){
   int i, n;
   float h;

   scanf("%d", &n);
   printf("%d\n", n);
   h = 0.0;
   i = 1;
   while (i <= n){
      h = h + 1.0/i;
      i = i + 1;
   }
   printf("%lf\n", h);
   return 0;
}

In the C version, the structure is almost the same, except that the do while of Fortran has been replace with a simple while. With the addition of the statement to increment the value of i, the loop “contents” are now enclosed within { and }. C also has another loop, the do/while() loop, that performs the loop once, then evaluates the condition at the end.

Ada

with ada.Float_Text_IO; use Ada.Float_Text_IO;
with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure harmonic is
   n, i : integer;
   h : float;
begin
   get(n);
   h := 0.0;
   i := 1;
   while i <= n loop
      h := h + 1.0/float(i);
      i := i + 1;
   end loop;
   put(h);
end harmonic;

In Ada, the while loop looks similar to that of the other to Fortran and C, it is just subtleties in syntax that set them apart. Here there are no parenthesis around the condition. Also note that in the for loop, the index variable, i, did not have to be declared, but here it does. Ada also provides a generic loop/end loop loop.

Julia

n = parse(Int64, chomp(readline()))
println(n)
h = 0
i = 1
while i <= n
   h = h + 1.0/i
   i = i + 1
end
println(h)

Same deal here. Similar to Ada, except the loop keyword after the condition isn’t needed. There are only two loops in Julia.

As you can see, over four languages, the only thing that fundamentally changes is the basic syntax of the loop.

spqr

Programming made easy – loops (ii)

With the basics of for loops, let’s look at an example of an actual program which calculates the Harmonic series, which is an infinite series of the form:

h(n) = 1 + 1/2 + 1/3 + … + 1/n

The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.  For interest sake, the loops are presented in reverse, i.e. 1/n + 1/(n-1) + … + 1, as it illustrates clearly how each language deals with the simple issue of a decreasing index. In each case the starting value of the index variable i is n, and the ending value is 1. Here it is the algorithm for the Harmonic series depicted visually, clearly showing the role of the loop:

Fortran

program harmonic
   integer :: n, i
   real :: h

   read (*,*) n
   h = 0
   do i = n,1,-1
      h = h + 1.0/i
   end do
   write(*,*) h
end program harmonic

Here the third item (the modifier) in the Fortran loop denotes the type of change to the loop index, in this case, a decrease by 1. In a  normal loop incrementing by 1, the modifier can be omitted.

C

#include <stdio.h>

int main(void){
   int i, n;
   float h;

   scanf("%d", &n);
   printf("%d\n", n);
   h = 0.0;
   for (i=n; i>=1; i=i-1)
      h = h + 1.0/i;
   printf("%lf\n", h);
   return 0;
}

In the C version, the loop index is decremented using the statement i=i–1. For more than one statement after the for loop definition, the statements would have to be encapsulated in { and }.

Ada

with ada.Float_Text_IO; use Ada.Float_Text_IO;
with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure harmonic is
   n : integer;
   h : float;
begin
   get(n);
   h := 0.0;
   for i in reverse 1..n loop
      h := h + 1.0/float(i);
   end loop;
   put(h);
end harmonic;

In Ada, the keyword reverse is used to specify a loop will be decreasing in value.

Julia

n = parse(Int64, chomp(readline()))
println(n)
h = 0
for i = n:-1:1
   h = h + 1.0/i
end
println(h)

Here the index modifier is placed in the centre, n:-1:1, implying i has the values n to 1, modified by -1 each loop iteration. In a  normal loop incrementing by 1, the modifier can be omitted.

spqr

Programming made easy – loops (i)

Humans are, by nature, repetitive beings. Watch the Star Trek: TNG episode “Cause and Effect”, and you will quickly understand what a loop is as the Enterprise is caught in a causality time loop. There are also times when programs must do a task more than once. If the repetition is limited to some countable number of recurrences with a foreseeable end then it is called a loop. And if, at least in the perception of the individual who is experiencing a certain situation, there is no end in sight then one is talking about endless or infinite loops. All of the above can be desirable or not. Here is a visual illustration:

The code in the program moves linearly from statement A, until it encounters a loop. At the start of the loop, the loop control tests some condition. If the condition is true, then the loop activates the piece of code (made up of one or more statements) in what is called the loop body. When that code is done the loop returns to the loop control, and the process starts all over. If the condition in the loop control becomes false, nothing happens, and the program ends the loop, and continues on to statement B. There is also a possibility that the first time into the loop, the condition becomes false, and in that case the loop is bypassed.

Loops are structures that allow for repetition – repeating an activity a number of times. There are different kinds of repetition:

  1. Loops where the number of repetitions is known before the loop activates.
  2. Loops where the number of repetitions isn’t known, and is controlled by some condition.
  3. Loops that are infinite, i.e. could continue to infinity and beyond.

The best example of the first case encountered in most languages is the for loop. Here we use a variable called a loop index to control the loop. Each time a loop loops it is called an iteration. So if the loop index is x, and it repeats 100 times, then x will begin with a value of 1, and increment by 1 each iteration, until x reaches 100. In Julia this is easily achieved in the following manner (in this case the loop simply prints out each value of x):

for x = 1:100
   println(x)
end

In Ada it takes a similar format (the printing part is a little different, but just ignore that bit):

for x in 1..100 loop
    put(x); 
    new_line;
end loop;

Ada uses the keyword loop to signify it as a loop. Fortran also uses a similar construct, but has never used the for loop, opting instead for the keyword do. Same concept, different name.

do x = 1, 100
   write(*,*) x
end do

C also uses a for loop, although it can be somewhat more convoluted:

for (x=1; x<=100; x=x+1)
   printf("%d\n",x);

All have their varied syntax, but achieve the same goal – a known number of iterations.

spqr

Coding Ada: Bitwise operators

In Ada, you can find similar bitwise operators to other languages: and, or, xor, and operators that shift left and right. The trick is that they use modular types. These types are unsigned and have “wrap-around” semantics. Consider the following declaration:

subtype byte is unsigned_8;
package byteIO is new ada.text_io.modular_io(byte);
x, y, z: byte;

This defines an integer type whose values range from 0 to 255 (on most processors), i.e. the integers that will fit in a byte. Since it’s “modular”, it means that arithmetic operations on the type wrap around (i.e. if you add 130 + 130, you will get 4. With this declaration, you can create binary numbers:

x := 2#00011110#;
y := 2#11110100#;
z := 2#11110000#;

Here x=30, y=244, and z=240. So we can then use bitwise operators (found in the Ada package Interfaces) to swap the numbers:

x := x xor y;
y := y xor x;
x := x xor y;

The numbers can be printed out with this code:

put_line(unsigned_8'image(x));
put_line(unsigned_8'image(y));

You can also use put from the sub-package byteIO:

byteIO.put(item => z, base => 2);

If we want to convert a number input from integer to type byte, we can do so in the following manner:

w: integer;
get(w);
z := byte'val(integer'pos(w));
byteIO.put(item => z, base => 2);

The byte’val returns the base type of byte. For example, if the value input by the user is 17 (w), then the value assigned to z will be 10001. What about shift operators? There is shift_left() and shift_right(). Here’s an example:

zs: byte; 
zs := shift_left(z,1);
byteIO.put(item => zs, base => 2);

If the user inputs 12, then the value of zs will be 24, as it has been shifted left 1 bit.

spqr

Programming made easy – nested loops

We’re not quite done with loops yet. There are still a few things to learn, although some can be left for later. There are certain situations where it is appropriate to use a loop inside another loop. Such a loop is called a nested loop. A nested loop is executed, essentially, from the inside out. Each loop is like a layer and has its own loop control, its own condition and its own loop body. Below is a schematic of three nested loops.

A loop inside a loop, inside a loop.

There are many different kinds of nested loops, and they are largely dependent on the underlying algorithm. Below are some examples of the types of nested loops that are possible.

Various examples of nested loops

We will consider how a nested loop can be used to create a times table. It basically works by iterating the inner loop 12 times for every iteration of the outer loop. So, 12 × 12 = 144 iterations. The outer loop is highlighted in blue, and the inner loop in red. Here is a sample output:

 1   2   3   4   5   6   7   8   9  10  11  12
 2   4   6   8  10  12  14  16  18  20  22  24
 3   6   9  12  15  18  21  24  27  30  33  36
 4   8  12  16  20  24  28  32  36  40  44  48
 5  10  15  20  25  30  35  40  45  50  55  60
 6  12  18  24  30  36  42  48  54  60  66  72
 7  14  21  28  35  42  49  56  63  70  77  84
 8  16  24  32  40  48  56  64  72  80  88  96
 9  18  27  36  45  54  63  72  81  90  99 108
10  20  30  40  50  60  70  80  90 100 110 120
11  22  33  44  55  66  77  88  99 110 121 132
12  24  36  48  60  72  84  96 108 120 132 144

Ada

with ada.Text_IO; use Ada.Text_IO;
with ada.Integer_Text_IO; use ada.Integer_Text_IO;
procedure nested is 
begin
   for x in 1..12 loop
      for y in 1..12 loop
         put(x*y, width=>4);
      end loop;
      new_line;
   end loop;
end nested;

Fortran

program nested
   integer :: x, y
   do x = 1, 12
      do y = 1, 12
         write(*,10,advance='no') xy
         10 format(I4)
      end do
      write(*,*)
   end do
end program nested

C

#include <stdio.h>
int main(void){
   int x, y;
   for (x=1; x<=12; x=x+1)
   {
      for (y=1; y<=12; y=y+1)
         printf("%4d", x*y);
      printf("\n");
   }
   return 0;
}

Julia

for x = 1:12
   for y = 1:12
      @printf("%4d", x*y)
   end
   println()
end
println(h)

spqr

Programming made easy – loops (iii)

There are of course other loops. These loops are normally used when the number of times a loop iterates isn’t known. These type of loops generally use some form of condition to control the loop. The most prominent type of loop is the while loop. A while loop checks a condition, and if true, processes the code in the loop body, otherwise it exists the loop. Unlike the for loop, which controls the values of the loop index in terms of updating its value, in the loops like while, this process must be added, i.e. the value of i is given the value 1, before the loop is activated, and its value is incremented within the loop body.

We will consider some of these loops using the same Harmonic series, this time in increasing order. The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.

Fortran

program harmonic
   integer :: n, i
   real :: h

   read (*,*) n
   h = 0
   i = 1
   do while (i <= n)
      h = h + 1.0/i
      i = i + 1
   end do
   write(*,*) h
end program harmonic

Here the index variable, i, must be initiated to the value 1 before the loop begins, and incremented within the loop. The condition states that the loop continues while the value of i is less than or equal to n, i.e. (i <= n) . Fortran also provides a more generic do/end do loop.

C

#include <stdio.h>

int main(void){
   int i, n;
   float h;

   scanf("%d", &n);
   printf("%d\n", n);
   h = 0.0;
   i = 1;
   while (i <= n){
      h = h + 1.0/i;
      i = i + 1;
   }
   printf("%lf\n", h);
   return 0;
}

In the C version, the structure is almost the same, except that the do while of Fortran has been replace with a simple while. With the addition of the statement to increment the value of i, the loop “contents” are now enclosed within { and }. C also has another loop, the do/while() loop, that performs the loop once, then evaluates the condition at the end.

Ada

with ada.Float_Text_IO; use Ada.Float_Text_IO;
with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure harmonic is
   n, i : integer;
   h : float;
begin
   get(n);
   h := 0.0;
   i := 1;
   while i <= n loop
      h := h + 1.0/float(i);
      i := i + 1;
   end loop;
   put(h);
end harmonic;

In Ada, the while loop looks similar to that of the other to Fortran and C, it is just subtleties in syntax that set them apart. Here there are no parenthesis around the condition. Also note that in the for loop, the index variable, i, did not have to be declared, but here it does. Ada also provides a generic loop/end loop loop.

Julia

n = parse(Int64, chomp(readline()))
println(n)
h = 0
i = 1
while i <= n
   h = h + 1.0/i
   i = i + 1
end
println(h)

Same deal here. Similar to Ada, except the loop keyword after the condition isn’t needed. There are only two loops in Julia.

As you can see, over four languages, the only thing that fundamentally changes is the basic syntax of the loop.

spqr

Programming made easy – loops (ii)

With the basics of for loops, let’s look at an example of an actual program which calculates the Harmonic series, which is an infinite series of the form:

h(n) = 1 + 1/2 + 1/3 + … + 1/n

The code for the program in Fortran, Ada, Julia and C is shown below. The loop is highlighted in blue.  For interest sake, the loops are presented in reverse, i.e. 1/n + 1/(n-1) + … + 1, as it illustrates clearly how each language deals with the simple issue of a decreasing index. In each case the starting value of the index variable i is n, and the ending value is 1. Here it is the algorithm for the Harmonic series depicted visually, clearly showing the role of the loop:

Fortran

program harmonic
   integer :: n, i
   real :: h

   read (*,*) n
   h = 0
   do i = n,1,-1
      h = h + 1.0/i
   end do
   write(*,*) h
end program harmonic

Here the third item (the modifier) in the Fortran loop denotes the type of change to the loop index, in this case, a decrease by 1. In a  normal loop incrementing by 1, the modifier can be omitted.

C

#include <stdio.h>

int main(void){
   int i, n;
   float h;

   scanf("%d", &n);
   printf("%d\n", n);
   h = 0.0;
   for (i=n; i>=1; i=i-1)
      h = h + 1.0/i;
   printf("%lf\n", h);
   return 0;
}

In the C version, the loop index is decremented using the statement i=i–1. For more than one statement after the for loop definition, the statements would have to be encapsulated in { and }.

Ada

with ada.Float_Text_IO; use Ada.Float_Text_IO;
with ada.Integer_Text_IO; use Ada.Integer_Text_IO;

procedure harmonic is
   n : integer;
   h : float;
begin
   get(n);
   h := 0.0;
   for i in reverse 1..n loop
      h := h + 1.0/float(i);
   end loop;
   put(h);
end harmonic;

In Ada, the keyword reverse is used to specify a loop will be decreasing in value.

Julia

n = parse(Int64, chomp(readline()))
println(n)
h = 0
for i = n:-1:1
   h = h + 1.0/i
end
println(h)

Here the index modifier is placed in the centre, n:-1:1, implying i has the values n to 1, modified by -1 each loop iteration. In a  normal loop incrementing by 1, the modifier can be omitted.

spqr

Programming made easy – loops (i)

Humans are, by nature, repetitive beings. Watch the Star Trek: TNG episode “Cause and Effect”, and you will quickly understand what a loop is as the Enterprise is caught in a causality time loop. There are also times when programs must do a task more than once. If the repetition is limited to some countable number of recurrences with a foreseeable end then it is called a loop. And if, at least in the perception of the individual who is experiencing a certain situation, there is no end in sight then one is talking about endless or infinite loops. All of the above can be desirable or not. Here is a visual illustration:

The code in the program moves linearly from statement A, until it encounters a loop. At the start of the loop, the loop control tests some condition. If the condition is true, then the loop activates the piece of code (made up of one or more statements) in what is called the loop body. When that code is done the loop returns to the loop control, and the process starts all over. If the condition in the loop control becomes false, nothing happens, and the program ends the loop, and continues on to statement B. There is also a possibility that the first time into the loop, the condition becomes false, and in that case the loop is bypassed.

Loops are structures that allow for repetition – repeating an activity a number of times. There are different kinds of repetition:

  1. Loops where the number of repetitions is known before the loop activates.
  2. Loops where the number of repetitions isn’t known, and is controlled by some condition.
  3. Loops that are infinite, i.e. could continue to infinity and beyond.

The best example of the first case encountered in most languages is the for loop. Here we use a variable called a loop index to control the loop. Each time a loop loops it is called an iteration. So if the loop index is x, and it repeats 100 times, then x will begin with a value of 1, and increment by 1 each iteration, until x reaches 100. In Julia this is easily achieved in the following manner (in this case the loop simply prints out each value of x):

for x = 1:100
   println(x)
end

In Ada it takes a similar format (the printing part is a little different, but just ignore that bit):

for x in 1..100 loop
    put(x); 
    new_line;
end loop;

Ada uses the keyword loop to signify it as a loop. Fortran also uses a similar construct, but has never used the for loop, opting instead for the keyword do. Same concept, different name.

do x = 1, 100
   write(*,*) x
end do

C also uses a for loop, although it can be somewhat more convoluted:

for (x=1; x<=100; x=x+1)
   printf("%d\n",x);

All have their varied syntax, but achieve the same goal – a known number of iterations.

spqr

Coding Ada: Bitwise operators

In Ada, you can find similar bitwise operators to other languages: and, or, xor, and operators that shift left and right. The trick is that they use modular types. These types are unsigned and have “wrap-around” semantics. Consider the following declaration:

subtype byte is unsigned_8;
package byteIO is new ada.text_io.modular_io(byte);
x, y, z: byte;

This defines an integer type whose values range from 0 to 255 (on most processors), i.e. the integers that will fit in a byte. Since it’s “modular”, it means that arithmetic operations on the type wrap around (i.e. if you add 130 + 130, you will get 4. With this declaration, you can create binary numbers:

x := 2#00011110#;
y := 2#11110100#;
z := 2#11110000#;

Here x=30, y=244, and z=240. So we can then use bitwise operators (found in the Ada package Interfaces) to swap the numbers:

x := x xor y;
y := y xor x;
x := x xor y;

The numbers can be printed out with this code:

put_line(unsigned_8'image(x));
put_line(unsigned_8'image(y));

You can also use put from the sub-package byteIO:

byteIO.put(item => z, base => 2);

If we want to convert a number input from integer to type byte, we can do so in the following manner:

w: integer;
get(w);
z := byte'val(integer'pos(w));
byteIO.put(item => z, base => 2);

The byte’val returns the base type of byte. For example, if the value input by the user is 17 (w), then the value assigned to z will be 10001. What about shift operators? There is shift_left() and shift_right(). Here’s an example:

zs: byte; 
zs := shift_left(z,1);
byteIO.put(item => zs, base => 2);

If the user inputs 12, then the value of zs will be 24, as it has been shifted left 1 bit.

spqr

Which programming language should you learn?

This question turns out now and then on forums, Facebook, and so on. Since I got tired of writing always the same things, I decided to write my suggestions here once for all.

As usually, with this kind of questions, everything depends on your starting point (are you a beginner? an amateur?) and your target (do you want to do web development? Contribute to open source projects? Program small devices like STM32?). Usually who asks this question is a beginner and does not say anything about specific goals, therefore usually I assume that the objective is to get some “culture” in this field. The answer that follows is written with this generic objective in mind.

Step 1 : learn to program (simplicity is the key)

If you have no experience in programming at all, I will suggest starting with something simple, in order to learn how to program before actually learning a language.

Yes, because “learning to program” is not the same of “learning a programming language.” Learning to program means learning how to decompose a problem into smaller problems and specify a procedure to solve them. Knowing how to do this is a skill that is independent on the specific language and somehow on a higher level than knowing programming languages. You can write programs without even having a PC, but just pen and paper.

Ada Lovelace, daughter of Lord Byron (yes, that Byron!), is considered the first programmer in history because of her notes to the article on the Analytical Engine designed (but never built) by Charles Babbage, a kind of computer of ‘800, but with the register made with gears and powered with steam… (I would suggest reading the Ada Lovelace article, it is very interesting)

Of course, even for learning the skill of programming a language is necessary, but I would stay on something simple.

A language that was suited for beginners, in my opinion, was BASIC. It was fairly popular in the ’80 when every home computer had some kind of BASIC interpreter built-in. Although simple, it had all the necessary features and one could write quite complex stuff with it, although the resulting code was not very maintainable. An advantage of BASIC was that it was interpreted: you could write a single command and having it executed immediately, without the need of an IDE.

Since BASIC is much less popular nowadays, I think that C is another good choice as a starting point since it is fairly simple. C is also quite low-level, giving you visibility of some machine level stuff like pointers and stack and this is useful because it gives you a sensibility about what happens “under the hood” even with other languages. (I find that this kind intuition helps me a lot when I learn a new language). Be sure to learn even all the tiny, obscure details of C such as pointers, struct, unions, functions with variable argument list (such as printf).

Also with C you will learn about macro expansion, a methodology used in several places and that requires a mindset slightly different from the one used in imperative languages like C. To be honest, I do not love macro expansion since it is quite error-prone and it can make the code less readable, but there are context where it is useful.

Second step: best practices & OOP with Ada

Since object-oriented programming (OOP) is widely diffused and fashionable, as a second language many would suggest C++ or Java. However, I am going to be heretic and suggest Ada. Beyond allowing OOP, it is a modern language, very powerful with strong emphasis on correctness and maintainability. It can introduce you also to stuff that it is not common in other languages such as contracts, type invariants and formal checking. Studying it you will learn some “good practices” in programming that will be useful even with other languages.

Since Ada is not widely used, finding information in the network is not easy. Few useful links: you can get an open-source, gcc-based compiler here: http://libre.adacore.com/. For an introduction to the language see the Adacore University, for an easy reference see the Wikibook, for a mix of resources see the Ada Information Clearinghouse (where you can find the reference manual) and the site of Adacore. Finally, you can meet other Ada-ists on the usenet group comp.lang.ada and on some LinkedIn groups.

Now you have the most important basics

Once you have a good experience of C and Ada, learning other languages is just a matter of learning a new syntax and maybe one or two new concepts. I, for example, learned Ruby in few hours just using a tutorial. In the end, most of the current languages are very similar one another.

Polishing it : Ruby/Python and assembly

Finally, to round everything up, I would suggest, as the cake icing, a scripting language like Ruby or Python and maybe some assembly. It is true that assembly is not used much nowadays (although it depends on your context), but some experience of assembly will give you some good understanding of what happens “under the hood.” Moreover, it is so much fun to go so close to the processor that you can almost feel the silicon... :-)

Strange stuff: functional languages, PROLOG, ….

If you really want the widest view, you can also try some fancy stuff like functional languages (Eiffel, Haskell, … even LISP) and logic programming stuff like PROLOG. Those languages have a “model” that is different from the usual “procedural” model. I did not see them used too much and I wonder if they are suited for very large scale and very long lived software, but it is useful to know that they exist and how they work.

Conclusions and final remarks

I hope that you found this useful or that, at least, gave you some ideas about programming. A final suggestion: my experience is that the best way to learn a new language is to use it. After you got acquainted with the syntax, choose a project of intermediate difficulty (even a silly one, it does not necessarily need to be useful) and do it (and, possibly, have fun…)

❌