Coding Ada: Using an exception

Some people wonder where you can use a simple exception in Ada. Functions are an ideal place. Below is a program which contains a function isNumber() which returns true if the string passed to it is considered a number (integer). So 1984 us a number, but x24 is not. The program takes a word as input from the user (as an unbounded_string), and passes it to isNumber(). The function isNumber() converts the unbounded_string to a string, and then to an integer using integer’value(). If the conversion works, then the function returns true. If however, the conversion fails, then a Constraint_Error exception will be triggered, and false will be returned.

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 number is

   aWord : unbounded_string;
   num: integer;
 
   function isNumber(s: unbounded_string) return boolean is 
      temp: integer;
   begin
      temp := integer'value(to_String(s));
      return true;
      exception 
         when Constraint_Error => return false;
   end isNumber;

begin
   put_line("Enter a word: ");
   get_line(aWord);
 
   if (isNumber(aWord)) then
      num := integer'value(to_String(aWord));
      put(num);
   else
      put_line("Not a number");
   end if;
end number;

This sort of code could be used to count numbers in a document or something similar. You can use float’value to do the same for floating-point numbers.

Advertisements

Why the Montreal Metro (subway) has good usability

Now I have talked about design usability before, and it is a global concept, which can be applied to anything which is used by humans. On a recent trip to Montreal, I rode on a number of the new Bombardier-Alstom MPM-10 subway trains on the Montreal Metro (STM). It is amazing how usable these trains are in comparison to the TTC’s Toronto Rocket trains. Now I get that the TTC’s cars are wider, and hold more people, and design specs likely came from the TTC, but there are just some things that could have been better thought out.

First off are the seats. Now this might not seem like a big item, because from a comfort point-of-view they are as comfortable as the seats on the TTC. Where they differ though is that the MPM-10 seats are made of plastic, versus the cloth covers on the Rocket. Why is this a usability issue? It relates largely to maintainability. If someone spills a drink on the MPM-10 seats, it is easy to clean off. The Rocket seats on the other hand will absorb and liquid poured on them, and result in increased maintenance.

The second point is holding bars for travellers. The MPM-10 trains have a bar in the middle of the car in front of each door. These poles spilt into three holding bars and allow people standing in the open space to hold onto something. The Rocket hold-on’s are confined to being on the edge of doors, or on the ceiling (and they had to retrofit more bars in some areas) – but there is still a lack of holdable regions. This may be for accessibility, but it is clear from the MPM-10, (which is less wide then the Rocket) that there is more than enough room for a wheelchair to board the train.

The signage for emergency stop, and personal security intercoms is extremely visible and easy to use. Some stations also provide floor-level signage which indicates what traffic flow will be when a train pulls in. All these items help the traveller make informed decisions, and help move people efficiently.

Doors open fast on the MPM-10. The software on the Rocket apparently does not open the doors until the train is at a complete stop, so is delayed, much longer than that of the MPM-10.

The question is how much usability testing do designers of subway cars do? Design is nice, but not if it doesn’t really work.

 

While C is a surfer dude, Ada is Thor

I like to think of C and Ada as two different personalities. C is the surfer dude of programming languages, sitting on the beach, being cool with everything, “Hey, I’ll compile the array that’s out of bounds… no problem”. It has a very easy-going way about things. C thinks using pointers is gnarly, and that you’re not really cool until your program is obfuscated (which really just means that the code is now speaking a different language, like surfer slang). With Surfer C there is never a problem, well, until there is. Programming in C is sometimes like being lured to sea by Sirens, we are bewitched by their song, and then getting caught in a rip, dragged out to sea. Ada on the other hand is the Thor of programming languages. Array out of bounds? Ada will smash down its hammer. It is a different experience. Ada enforces type compatibility which makes sure we don’t use incompatible types.

Now all this has to do with how they were brought up. C is “weakly typed”, and Ada is “strongly typed”, like its predecessors Pascal, Euclid and Modula. If you have never heard these concepts before, let’s take a moment to understand them. Typing, i.e. whether a language is weak or strong, which are somewhat vague terms. The quasi difference between a strongly typed language and a weakly typed one is that a weakly typed one makes conversions between unrelated types implicitly. A strongly typed language, on the other hand, typically disallows implicit conversions between unrelated types. Strong typing means that it is impossible to concatenate a string with a floating-point number. In C, not every type is checked, and so it is considered fairly weakly typed. Consider the following piece of code in Ada:

i : integer;
u, v : float;

v := 5.6;
i := 2;
u := v + i;

This code will fail to compile, resulting in an error message of the form:

typeeg.adb:15:11: invalid operand types for operator "+"
typeeg.adb:15:11: left operand has type "Standard.Float"
typeeg.adb:15:11: right operand has type "Standard.Integer"

To fix this problem, you actually have to explicitly convert i, i.e. float(i). Ada will not do an implicit type conversion from integer to float, C on the other hand will do an implicit conversion. Fussy? Maybe, but it does lead to fewer inadvertent mathematical errors. Conversely, consider this convoluted piece of code in C:

int x = 0;
void *v = &x;
char *c = v;

printf("=%c=\n", *c);

Code it, run it. The result is interesting. Not the sort of code you really want people to create. (You cannot create a void variable, but you *can* create a pointer to void).

It’s also about the job they do. C is a systems programming language, which is often used to build things like embedded systems, or even compilers for other programming languages. C is considered by some to be a WYSISWYG language – looking at a C program gives a good indication of what the lower level combined code will look like. That’s why C is such a good language for lower-level software that interacts with hardware. On the other hand, it is not really known how well such languages scale to large systems (we develop large systems, but who has ever evaluated the software development process for  programs 50 million lines long?). In addition, C’s focus is on efficiency, and as such it sacrifices checks that other languages make – reliability, safety and security can sometimes be compromised. Ada on the other hand was designed for embedded systems, multi-tasking, and dealing with real-time programming. For instance in the aerospace, or transport industries – driverless trains anyone?

People will argue that C is better because it is, well, C! Ada is too unwieldy. But I know I would prefer to drive in a car/plane/train built in Ada over one built in C (well, I would be okay if the programmers were truly experts), but better C than C++, or heaven forbid Java.

 

Coding Cobol: dynamic filenames

So how do we prompt for a filename in Cobol?

identification division.
program-id. fileio.

environment division.
input-output section.
file-control.
select ifile assign to dynamic ws-fname.

data division.
file section.
fd ifile
   record contains 88 characters.
01 student-info.
   05 student-name occurs 4 times.
      10 stdnt-name pic x(15).
      10 stdnt-idno pic x(7).

working-storage section.
01 i pic 9.
77 ws-fname pic x(30).

procedure division.

   display "Filename containing book information? ".
   accept ws-fname.

   open input ifile.
      read ifile
   end-read.
   close ifile.

   move 1 to i.
   perform print-out until i is greater than 4.
   stop run.

print-out.
   display "Student name is " stdnt-name(i).
   add 1 to i.

Here’s what a potential data file has in it (Each record has 22 elements, 15 for the student name, and 7 for the student number):

Skywalker      6543287Ackbar         1189283Chewbacca      9882870Palpatine      0000001

One line of code in the environment division specifies the dynamic filename:

select ifile assign to dynamic ws-fname.

The output from this program is:

Student name is Skywalker
Student name is Ackbar
Student name is Chewbacca
Student name is Palpatine

 

Are autonomous vehicles that important?

I’m not a fan of technology (and if you’ve read my previous ramblings you’ll know that). The problem with technology is that humans tend to move forward with change far too quickly. Sometimes, such as in the case of electricity we get lucky, and it works relatively well (well maybe except for when we decided to use aluminum wiring instead of copper). Other times, such as in the case of nuclear stuff, we take the short term view of things, and leave the long term to well… the future. Problem is the future is never really that far away, and it always comes back to bite us. Fossil fuels likely weren’t a super great decision either.

So now in the computer age we think that AI, and things like autonomous vehicles will change the way we live. That may be true, but that doesn’t mean it will out to be a positive change.

What’s wrong with autonomous vehicles?

  1. Too much data – There is too data involved, and too many external factors that could influence how a vehicle works. A bird flying into the windshield, a vehicle out of control, a moose crossing the road int he dark etc. Can technology deal with that much data from that many sources?
  2. The wrong programming languages – Scuttlebutt on the net says these systems are being written in C/C++. C I get, it is a systems language. C++, I’m not so sure about. It’s being used on the F-35 and that’s a software disaster. Even C++’s maker, Bjarne Stroustrup once said “C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off”. Enough said about that. Udacity is building what seems like an open-source self-driving car using Python. – REALLY, who thinks *that’s* a good idea?? There is an little language called Ada, which is perfectly suited to moving vehicles, and has been heavily used in aerospace and rail projects. So programmers would have to learn a real-time language… and??
  3. Humans making software  – There is no guarantee that the algorithms designed for an autonomous vehicle will be robust because they are written by humans. Unlike planes int he sky, or trains on rails, there are 1,000,001 more scenarios a car has to deal with. The recent fatal pedestrian crash involving a fully autonomous  vehicle in Arizona speaks volumes. How many deaths will we consider acceptable, and who is culpable?
  4. More technology – Is not always a better thing. It a combination of huge amounts of data, AI, and potentially 100’s of millions of lines of code. Do we have the infrastructure to create such vast pieces of software. I beg to question that even for an iPhone (and it doesn’t do much).

Look, I’m not against progress. But humans don’t exactly have a great track record when it comes to rolling out technology advances in an expedited manner.

Besides last time I looked, the need for autonomous vehicles doesn’t rate rate high when you consider we could put those resources to making sure the planet isn’t in a worse condition by 2100.

C language: The good, the badly, and the ugly

C is a language used by many a programmer, and it is an interesting language. But here’s the thing, it was never designed to teach people how to program. It’s a great language for people who have a basic understanding of programming principles, but for a novice programmer, it just doesn’t make the grade. Let’s explore why.

The Good

Let’s start off with the good. C only uses 32 reserved keywords, which is extremely good from the perspective of learning the entirety of the language. On the other end of the scale, Java has 50, and C++ has the 32 keywords of C, with an additional 30 keywords, for a total of 62. So, C has brevity on its side, which is good. C also allows for access to low-level programming, some have likened it to “assembler with steroids”. This is a double edged sword, because it makes the language powerful, but it also makes it unwieldy for a novice programmer. It is also a very powerful language, and that is best illustrated by the fact that a number of compilers for other languages are written in C. However  Python has 33 keywords and is inherently easier to deal with.

C is also a pure language, unlike many other languages are multi-paradigm, or use concepts such as OO. Not that OO is bad, it’s just a real distraction to have to deal with concepts such as inheritance and polymorphism. However if you learn C, it is easier to transition to languages with a similar structure, such as C++, and even Java. Other good things? I have to strain to think of some… for the novice anyway.

The Bad

For the novice programmer, who knows very little about the intricacies of memory, C can be a horrible language to learn to program in. This manifests itself in the first time a programmer writes a scanf() statement. Consider this piece of code:

int nmbr;
scanf("%d", &nmbr);

To a veteran programmer, this is not an issue. To a novice, they are forced to understand that the ampersand character in the clause &nmbr is used to store the value input by the user from the keyword in the memory position associated with the integer variable nmbr. Quite a daunting task. Failure to add the & will result in a problem int he form of a Segmentation fault: 11. But the compiler *will* compile the code, giving the programmer the false sense of security by thinking that their code is okay. This could not be further from the truth. Now the novice programmer has to try and figure out what a Segmentation fault: 11 means.

This reliance on memory does not go away. It forces itself upon the programmer again in the guise of pointers in the context of function parameters, and dynamic memory if a large amount of space is need to store some piece of data. It can also inadvertently appear in the form of insufficient memory associated with the stack. You have to understand memory to program in C, it’s unavoidable. In addition, C allows programs with errors to run. Consider the following code:

int a = 0;
if (a = 1)
   printf("valid");

C allows assignment statements within an if conditional, so the fact that a is set to equal 1, means that the condition will always be true, regardless of what a‘s value is coming into the if statement. There are also deep issues with a failure to check array bounds, and overwriting memory.

The UGLy

Ugliness in C manifests itself in the compactness of the language. Firstly through the use of compact operators such as ++, ––, &&, ||, += etc. These operators likely made a lot of sense when C was first introduced, because they likely helped reduce machine instructions (many were first used in preceding language such as CPL, BCPL, B, etc). However to the novice programmer, the i=i+1 is inherently easier to write than i++, because it is understandable (once they get past i=i+1 as a programming statement, not a mathematical one).  The use of operators such as ++ serve to confuse the novice programmer, because in certain contexts such as:

int p = 4;
p++;
printf("%d", p);

The value of p is 5, whether or not p++ or ++p is used. However used in this context:

int p, x;
p = 4;
x = p++;

The value assigned to x is 4. Change p++ to ++p, and the value of x becomes 5. This is because p++ means “use the value of p, then increment p by 1, and ++p means “increment p by 1, and then use its value”. Subtle, yet bound to make an algorithm fail. The novice programmer doesn’t need this (and I would argue the rest of us don’t either). There are similar issues using && for and, etc.

There is also things like the way arrays are indexed. The most common way is something like a[x], where x is the index. However in C it is also possible to write x[a], which is super confusing for the novice. This is because a[x] means *(a+x) and x[a] means *(x+a).

Ugly? Yes.

Oh, and some control structures that have somewhat obtuse structures (e.g. switch), or lack consistency, such as the while and do-while loops. The while loop does not require enclosing parentheses, unless there is more than one statement. The do-while loop does require parentheses. Lack of consistency causes recall issues amongst novice programmers.

The BORING

I add this last category, because frankly, C is a boring language. There are things that can be done with C, but it takes a good amount of experience with the language. Starting with the bare bones language, there is nothing inspiring which can be done. No graphics, no processing images, no fun stuff. So it is inherently hard to motivate novice programmers, when the pinnacle of fun is outputting Factorials, or a “cool” sorting algorithm.

A weird C memory bug

The there day in one of my classes I was attempting to show how C tends to ignore array out-of-bounds problems. Here is the code in question:

#include <stdio.h>

int main(void)
{
   int x[100];
   int i;

   for (i=0; i<150; i=i+1)
   {
      x[i] = 0;
      printf(" %d %d\n ",i , x[i]);
   }

   return 0;
}

Normally this code will work to a point and possibly crash – I mean all it does is try and overwrite 50 pieces of memory it has no access to. It does this by assigning each element in the array the value 0, an print out those values. However, when I ran the code it did something I did not expect it to do.

The program ran through until element x[102], then it reset and ran through it again – infinitum. Change the value of the number being assigned to the elements, say to x[i]=12, then the next iteration, and all those that follow, start with i=12. Somewhere it is resetting the loop variable, and it has something to do with the memory being overwritten.

...
101 12
102 12
12 12
13 12
...

Is this a case of a heisenbug – a bug that seems to disappear or alter its behavior when one attempts to study it? Unlikely, because it doesn’t change its behaviour. But it is extremely strange behaviour. It also aptly illustrates why C can be dangerous sometime, and  why some people call C “death by a thousand cuts”.

P.S. It may be unlikely that anyone else will experience the same thing when running this piece of code on their system.

Coding Cobol: Basic re-engineering

The challenging part of re-engineering Cobol programs is to identify structures in need of being “updated”, or removed in the case of redundant features. This section deals with some of these issues, although it by no means covers everything.

Add end-if

All conditional statements which still use the next clause, or implicit terminators like a period should be transformed so that they are terminated by the explicit terminator end-if. This makes the code more consistent and removes redundant instructions (e.g. next). For example:

para-1.
   if x > 0 
      go para-2
   else
      next sentence.
   display ‘x’.
para-2.

is converted in the following manner:

para-1.
   if x > 0 
      go para-2
   end-if.
   display ‘x’.
para-2.

eliminating goto

Eliminate jump instructions to reduce the amount of unstructured spaghetti-code. For example:

para-1.
   if x > 0 
      go to para-2
   end-if.
   display ‘x’.
para-2.

would be re-engineered to look like:

para-1.
   if x > 0 
      continue
   else
      display ‘x’
   end-if.
para-2.

Note that the role of the continue statement is to prevent empty portions of the if statement. This can be taken a step further in the next section, which removes code containing continue statements that are not necessary.

Eliminate unnecessary continue

Eliminate continue instructions that are deemed not necessary. For example:

para-1.
   if x > 0 
      continue
   else
      display ‘x’
   end-if.
para-2.

could be modified by changing the conditional:

para-1.
   if not x > 0 
      display ‘x’
   end-if.
para-2.

Sometimes it is easier to add a continue statement during earlier processing, and remove the redundant ones later as a post-processing step.

Restructuring while

In dialects of Cobol 74 there was no while construct available, so it was often simulated using a go to. This is a loop in Cobol 74:

loop-one.
   if expr 
      ...
      go to loop-one
   end-if.

And this is the equivalent loop in Cobol 85:

loop-one.
   perform until not expr 
      ...
   end-perform.

 

 

 

 

 

Coding Cobol: A program with loops (and an array)

To illustrate some loops (and arrays) in Cobol, let’s look at a Bubblesort algorithm in Cobol (although Cobol has a rich built-in sorting functionality). This program prompts the user for the number of items to enter, inputs them, and sorts the list.

identification division.
program-id. bubblesort.

data division.
working-storage section.
01 n            pic 99.
01 array.
   02 unsortedA pic s9(3) occurs 100 times.
01 temp         pic s9(3) value 00.
01 i            pic 99.
01 j            pic 99.
01 jp1          pic 99.

procedure division.

   display "How many numbers to sort? ".
   accept n.
   move 1 to i.
   display "Enter ", n, " numbers: "
   perform until i > n
      display i
      accept unsortedA(i)
      add 1 to i
   end-perform.

   compute i = n - 1.
   perform until i < 1
      move 1 to j
      perform until j > i
         compute jp1 = j + 1
         if (unsortedA(j) > unsortedA(jp1))
            move unsortedA(j) to temp
            move unsortedA(jp1) to unsortedA(j)
            move temp to unsortedA(jp1)
         end-if
         add 1 to j giving j
      end-perform
      subtract 1 from i giving i
   end-perform.

   move 1 to i.
   perform until i > n
      display i ":=" unsortedA(i)
      add 1 to i
   end-perform.
   stop run.

The first thing you will notice is the array declaration:

01 array. 
   02 unsortedA pic s9(3) occurs 100 times.

“Arrays”, such as they are in Cobol cannot be created using a level 01 specification. In this declaration the array as a complete entity is created as a level 01, and it’s element is a level 02, to hold 100 numbers, 3 digits in length (try and store 9761 here and it will truncate it). The main part of the program just performs a Bubblesort, what we are interested in here is how the loops function. In Cobol you won’t find any fancy words like for, while or loop. Loops are pure weirdness (but then again from a pure usability viewpoint, the words perform until, are very descriptive, more so that for). Here is the loop for the user to input n integers:

move 1 to i. 
display "Enter ", n, " numbers: " 
perform until i > n 
   display i 
   accept unsortedA(i) 
   add 1 to i 
end-perform.

Now because of the structure, the loop control variable i has to be initialized before the loop begins, and incremented within the loop. In this case the loop uses “perform until“, which provides for an exit condition (rather than “do this while true“). The nested loop just uses two perform “loops”… nothing untoward here.

In fact there is only one real trick in this program. The comparison in a Bubblesort is normally written like this:

 if (unsortedA(j) > unsortedA(j+1))

But, Cobol won’t allow this. It wants to see a single index, and j+1 just doesn’t cut it. So that is why the code instead calculates this value prior to using it:

compute jp1 = j + 1 
if (unsortedA(j) > unsortedA(jp1))

Some languages just do things differently. Now there are other loops in Cobol:

  • perform thru – executes a series of paragraphs.
  • perform until – perform until the condition becomes true.
  • perform times – perform a paragraph a number of times.
  • perform varying – perform a paragraph till the condition in the until phrase becomes true.

 

Coding Cobol: An alternate program

In the previous post, we looked at a program with calculated the type of a triangle. Now let’s look at a similar program which takes a filename as input, removing the restriction of the hard-coded filename. There are also some other subtle changes in how the file is accessed. Here is what the program now looks like:

identification division.
program-id. triangle.

environment division.

input-output section.
file-control.
select input-file assign to dynamic ws-fname
   organization is line sequential.

data division.
file section.
fd input-file.
01 integer-triple.
   03 i           pic 9(5).
   03 j           pic 9(5).
   03 k           pic 9(5).

working-storage section.
77 ws-fname       pic x(30).
77 match          pic 9.
   88 scalene     value 0.
   88 isosceles   value 1.
   88 equilateral value 3.
77 a-message      pic x(100).
77 eof-switch     pic 9 value 1.

procedure division.
   display "Filename? ".
   accept ws-fname.

   open input input-file.

   perform computation until eof-switch = 0.
   close input-file.

   stop run.

computation.
   read input-file into integer-triple
      at end move zero to eof-switch
   end-read.
   if eof-switch is not = 0
      if ((i+j) > k) and ((j+k) > i) and ((k+i) > j) then
         perform triangle
         perform print
      else
         move "Not a triangle" to a-message
         perform print
      end-if
   end-if.

triangle.
   move zeros to match.
   if i is equal to j then
      add 1 to match
   end-if.
   if j is equal to k then
      add 1 to match
   end-if.
   if k is equal to i then
      add 1 to match
   end-if.

   if scalene then
      move "scalene triangle" to a-message
   else
      if isosceles then
         move "isosceles triangle" to a-message
      else
         if equilateral then
            move "equilateral triangle" to a-message
         end-if
      end-if
   end-if.

print.
   display "Sides: ", i, j, k
   display a-message.

The code which deals with the file allows the user to enter a filename through standard input. This requires a modification to the specification in the file control section.

file-control. 
select input-file assign to dynamic ws-fname 
   organization is line sequential.

Here a string, ws-fname, is association with the file handle, which is declared in the working-storage section.

77 ws-fname     pic x(30).

The “main” part of the program is modified, so that the filename can be input, and then the paragraph computation is executed until the end-of-file variable is set to zero. This effectively allows for multiple triangles to be evaluated (one set of data per line).

procedure division. 
   display "Filename? ". 
   accept ws-fname. 

   open input input-file. 
   perform computation until eof-switch = 0. 

   close input-file. 
   stop run.

Inside computation, the file is read, and eof-switch is set to zero when the EOF is encountered.

read input-file into integer-triple 
   at end move zero to eof-switch 
end-read.

The only other change (apart from a couple of new variables), is that after the triangle data is read, if not EOF, then the triangle data is processed.