What the Authors of “Hello, World!” Don’t Tell You About

Web Development

As a rule, the adherents of The-very-best-language write their promotional mini-programs something like this:

ageOfBob = 0
ageOfMary = 0

print("Input Bob's age: ")
read(ageOfBob)

print("Input Marry's age: ")
read(ageOfMary)

// Do the math
if (ageOfBob > ageOfMary)
   print("Bob is older than Mary by ", ageOfBob - ageOfMary, " years")
else if (ageOfBob < ageOfMary)
   print("Mary is older than Bob by ", ageOfMary - ageOfBob, " years") 
else 
   print("Mary and Bob are of the same age")

It’s assumed that a newcomer will like another simplified version of the C-like syntax with automatic type conversion, without unnecessary semicolons, with simple names of standard functions, and so on.

If the newcomer becomes really interested in The-very-best-language, it will be too late to retreat by the moment he has to write real programs in accordance with the recommendations for writing safe code for serious clients or serious employer:

const MAX_PERSON_AGE = 120
const MIN_PERSON_AGE = 1

int getAge(string name) {
   age = 0

   print("Input ", name, "'s age: ")
   read(age)

   if (age < MIN_PERSON_AGE or age > MAX_PERSON_AGE)
      throw IncorrectAgeInputException
   else 
      return age
}

try {
   ageOfBob = getAge("Bob")
   ageOfMary = getAge("Mary")
} catch (IncorrectAgeInputException) {
      print("You're doing it wrong!")
}

// Do the math
...

So, four stings of code turned into a definition of a few constants (since magic numbers in code is bad) and a function (see DRY) that throws an exception. If we also remember that the getAge function should be covered with at least a pair of unit tests…that’s a separate story.

In practice, such a simple example is easily generalized to a wide class of problems related to processing of the external input, when the program receives obviously unknown values that can be anything.

Now, let’s see how features of strict typing can help us in solving this task.

We’ll rewrite our program in Ada. Since 1983, Ada has had the feature “if it compiles, it works” that is now part of what Haskell and Rust are promoting. In addition, programs in Ada compile in the native code and can also run on microcontrollers in real time, not much inferior to the C language in performance. Anyway, let’s focus…

with ada.text_io, ada.integer_text_io, ada.io_exceptions;
use  ada.text_io;

procedure main is
   type Age is range 1 .. 120;

   package io is new ada.text_io.integer_io(num => Age);

   ageOfBob, ageOfMary : Age;
begin
   put_line("Input Bob's age: ");
   io.get(ageOfBob);

   put_line("Input Mary's age: ");
   io.get(ageOfMary);

   -- Do the math
   if ageOfBob > ageOfMary then
      put_line("Bob is older than Mary by" & Age'Image(ageOfBob - ageOfMary) & " years");
   elsif ageOfBob < ageOfMary then
      put_line("Mary is older than Bob by" & Age'Image(ageOfMary - ageOfBob) & " years");
   elsif ageOfBob = ageOfMary then
      put_line("Mary and Bob are of the same age");
   end if;

exception
   when ada.io_exceptions.Data_Error =>
      put_line("You're doing it wrong!");
   when others => null;
end main;

Compared to the simplest first version of the program, we only added a new type Age with an explicitly defined range of values:

type Age is range 1 .. 120;

We also used the ada.text_io.integer_io package, which was parameterized of that type:

package io is new ada.text_io.integer_io(num => Age);

Now, when calling io.get(ageVar) function, in which ageVar is a variable of type Age, the number entered by the user will be checked. In case it does not correspond to its type Age the Data_Error exception will be generated.

It can often be heard that Ada is a complicated, verbose and difficult to learn language. I’ve provided an example of how “simple” at the first glance languages just shift some work to the programmer, while “difficult” languages, that might require more time on learning all of their features, allow us to save time on debugging and tests in actual development .

Comments

1,128

Ropes — Fast Strings

Most of us work with strings one way or another. There’s no way to avoid them — when writing code, you’re doomed to concatinate strings every day, split them into parts and access certain characters by index. We are used to the fact that strings are fixed-length arrays of characters, which leads to certain limitations when working with them. For instance, we cannot quickly concatenate two strings. To do this, we will at first need to allocate the required amount of memory, and then copy there the data from the concatenated strings.