Magna Carta — Language Agnostic Reasoning

Chukwunonso Nwafor
5 min readMay 27, 2021

Stop…. Think, Plan, then Code.

When in doubt, choose efficiency.

Don’t call hardware-related stuff, UNSAFE, you might offend the digital world and its representatives.

Jordan Harrison — unsplash

Introduction

Consider a laborer tasked with clearing a land. In his toolbox, a cutlass. With the cutlass he can be able to finish his work. Now imagine if he is given a lawn mower, well you can agree with me that if he puts in the right amount of effort with the lawn mower, he can be able to finish his work on time and of course more conveniently.

Many a programmer put more emphasis on the tool instead of the task assigned. A task can be solved using C++, C, Java etc. but all languages are not equal. Like George Orwell’s animal farm, “All languages are equal, but some are more equal than others”. A programmer must see a language as a tool to an end.

We also have to understand and appreciate the fact that some languages are created for specific domains. For example, JavaScript for the browser environment. It would be nonsensical to say you want to use say Java for the browser. It is just not created for that domain except maybe if you compile to JavaScript or an alternative like Wasm.

Two ends of the Spectrum

At the extremes, we have the digital world (represented by the computer) and the physical world (represented by the programmer). A programmer needs to map the constructs of the physical world to the digital world.

Modeling Reality

A computer understands bits (0’s and 1’s, low’s and high’s etc.). While a programmer can reason using bits, he would be more productive using constructs that best reflect the problems he deals with in the physical world.

A programmer knows mathematical reasoning. He can conveniently work with sets and multisets thus he understands the notion of character sets and symbols sets. He knows number theory thus he understands types like the integers, reals and there associated operations. He knows logic thus he understands true and false, AND, OR etc. He knows algebra thus he understands and uses identifiers to represent abstract things.

But how can a programmer map these to the resources the computer offers. Mind you, a computer might offer resources like the processor, network adapter, memory, screen, camera, disk etc. More importantly, how can a programmer access these resources to complete his task. Surely if he wants to create a video conference software, he must utilize the camera, the network adapter, the screen, the disk etc.

A Computer’s Resource

A computer provides different resources. Consider that a programmer wants to persist data on disk. Well using a file abstraction, he has to open the file, write to the file, then close the file.

If you consider the fact that most computers are multi-user, multi-threaded, multi-processed, multi-tasked, then you now have to account for the fact that the disk might be in use by another user, thread or process etc. If in use, should you wait?, how long will you wait?, should you abscond?. How would you specify these different concerns. Most abstractions of a computer’s resources use terms like blocking, non-blocking, asynchronous, synchronous etc.

Language Evolution

The characters used by a language to represent its constructs must come from a character set. The very implementation of a language assigns meaning to the character sequences that are well-formed according to its syntax. However these constructs are the primitives of the language and they must come from a language’s symbol or token set.

Tokens or symbols usually include keywords, operators, delimiters, literals, identifiers, comments etc.

The question now is, what are the basic constructs required in a language that a programmer can use to solve his problems. Well, types must be there. expressions must be there, variables must be there, statements also etc.

Basic types

Assume our language has four basic types integer, character, real, and string. If I introduce two keywords into the language let and be, together with the identifier token, the assignment operator and a statement terminator, I can declare variables to be of type integer, assign values to it then perform an operation called an expression, then print out the expression assuming we are provided the print utility, using the following character sequence.

let a, b be integer;
a = 2; b = 3;
print(a+b);

Evolution 1 — promoting reuse using subroutines

We want an identifier we can always call like we do in mathematics. Thus we add functions to our language. With it we introduce the keywords function and return, start and end. Re-writing our example above to print the some of the arguments passed to it, we have

function sum(let a, b be integer) : integer
start
return
a+b;
end
print(sum(2, 3));

Evolution 2 — subroutines that don’t return values

We introduce the keyword procedure to account for subroutines that don’t return values.

procedure print_sum(let a, b be integer)
start
print(a+b);
end
print_sum(2, 3);

Evolution 3 — user-defined types (a container of primitive types)

Assuming we are told to model the details of an employee of an organization, with the current state of our language, we can do something like:

let first_name, last_name be string;
let salary be real;
let age be integer;
let gender be character;
first_name = "Obi";
last_name = "Nwala";
salary = 80000.0;
age = 23;
gender = 'M';

Now assuming we want to increase Obi’s salary by $50,000 after the first year, we can do something like this:

salary = salary + 50000.0;

Now assuming I want to create record for Adaku and Adaugo, do I have to declare types like this for them. You can see that this can easily get out of control. How can we go about solving this problem.

Enter the user-defined type. We group variables of primitive types or other user-defined types and create variables of this user-defined types to represent each individual employee.

We introduce keywords struct. We show an example use below.

let Employee be struct
start
first_name: string;
last_name: string;
salary: real;
age: integer;
gender: character;
end
let Obi, Adaku, Adaugo be Employee;Obi.first_name = "Obi";
Obi.last_name = "Nwala";
Obi.salary = 80000.00;
Obi.age = 23;
Obi.gender = 'M';
Adaku.first_name = "Adaku";
Adaku.last_name = "Nweke";
Adaka.salary = 85000.00;
Adaku.age = 22;
Adaku.gender = 'F';

We can then increase Obi’s salary as

Obi.salary = Obi.salary + 50000.0;

Continued in Part 2.

--

--