
-----------------------------------
wtd
Thu Nov 25, 2004 12:53 am

Manual draft, chapters 1 - 14 with Foreword
-----------------------------------
Foreword

The purpose of this document is to introduce programming and good practices when programming.  To accomplish this I will be showing an awful lot of code.  Do not be daunted by this.  First it's largely because I'm demonstrating the concepts in two languages for various reason explained in the next chapter.

Secondly, much of the code in this document is exactly the same.  Why would I do this?  Well, quite simply, I believe that it helps the learning process to introduce at most one or two new concepts at once.  I start out very simply and slowly add more to a program.  By doing so I start out each chapter with something that looks very familiar from he previous chapter.

I do expect that people reading this document will gain experience and confidence as they go along.  I strongly advise readers to try each bit of code as they go along.  Expecting this, I may provide less in the way of explanation in later chapters than I do in earlier chapters.

I will not provide much in the way of explanation of syntax throughout the document, except perhaps where it's unusual or inconsistent in some way.  I expect readers will be able to see patterns in code, and providing samples in two languages should help.  A reader should look at a sample in Turing, and a sample in Ada95 and see the similarities, as well as the differences.

For instance, in:

put "Hello, world!"

And:

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
begin
   Put_Line("Hello, world!");
end Hello_World;

The reader should notice that:

put "Hello, world!"

And:

Put_Line("Hello, world!");

Serve the same purpose, and should be able to discern therefore that the rest of the second program is specific to the language.

Chapter 1: Background

Why do we have computers?

Computers exist for a singular purpose: to serve human beings, making complex, time-consuming calculations easy and quick.  They can't think for us, but they can free us from having to do the menial, repetitive work.  This allows us to focus on solving more interesting problems.

What is programming?

Programming is the art and science of making computers work for humans.  When we describe a programming language as "low-level" or "high-level", we're talking about how far the language is from the machine.  The farther away the language is from the machine, the more we've allowed ourselves to think in human terms, rather than machine terms.

Aside from very specific situations, our goal should be to write programs for other humans who have to read and understand the program, and let the computer do the menial work of decoding what we mean.  Achieving that is the focus of the following content.

What language will this document use?

For the purposes of this document, I'll be using Turing 4.05.  It's a reasonably high-level language.  If not as good in that regard as other languages, it is at least well-known among the target audience.  

Unfortunately, it is not freely available.  As a result, I'll be giving examples in Ada95 as well, a language which you can freely use, and which bears a considerable syntactic similarity to Turing.  An installer for Windows can be downloaded Chapter 2: Hello, world!

What good is a computer without output?

Generally, if we don't see some result from running a program, there's very little to write the program.  As a result, programming languages typically contain some standardized way to display output.

What kind of output will we be seeing?

That's a good question.  The output we'll be seeing is purely text-based.

Why not pictures?

Graphics are all well and good, but the focus of this document is on good programming practices.  The ideas presented within it apply equally well to text-based and graphical output, and by excluding graphics, we reduce the complexity of the program.  I don't want people worrying about how to make their fonts purple, when they should be worrying about whether they'll be able to read their own code in a week.

So, let's say "Hello, world!"

Turing:
put "Hello, world!"

Ada95:
with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
begin
   Put_Line("Hello, world!");
end Hello_World;

Picking it apart

The Turing sample is very simple.  "put" is a command which instructs the computer to output whatever follows it and then skip to the next line.  "Hello, world!" is a "string": a set of characters we can print.

The Ada sample is less simple, but the reasons for that lack of simplicity will be clear later.

Chapter 3: What's in a language?

So we've talked about programming languages, but we've yet to dispel a common source of confusion.  In human languages we clearly draw the line between the rules of the languages, and the vocabulary.  There are certain ways we put sentences together, and then there are the words themselves.  It isn't unheard of for new words to get added to the English language, but the basic rules remain the same.

The same applies to programming languages.  We have parts of a programming language that are just part of the language, and inseparable from it.  At the same time, we also have parts that correspond to words, and we can even create our own "words".  

Let's revisit "Hello, world!"

In our Turing program, "put" is part of the language.  

This is the primary difference between the Turing and Ada examples.  In the Ada example, "with", "use", "procedure", "is", "begin", and "end" are all part of the language, as are the semicolons which end statements.

The two lines doing the work in each program are:

put "Hello, world!"

Put_Line("Hello, world!");

Whereas the first is an integral part of the language, the second is just a "word".  In this case it's a procedure which prints out a string to the screen.  It's part of the "Ada.Text_IO" package we included via the "with" statement.  The "use" statement means I don't have to write the following.

Ada.Text_IO.Put_Line("Hello, world!");

Chapter 4: What's a procedure?

In short, a procedure is a chunk of programming language code grouped together for the purpose of accomplishing some single task.  By doing this, we also gain the ability to give it a name that has more meaning to us.  

Hello, again

We return to our simple "Hello, world!" program.

put "Hello, world!"

This is pretty concise, and not too hard to figure out, but it doesn't really tell someone reading the program what I was trying to do.

So we create a simple procedure called "greetWorld" that wraps up this code.  Notice we gave it a verb-style name.  That's because verbs do things in human languages, and procedures do the same in programming languages.

procedure greetWorld
   put "Hello, world!"
end greetWorld

And then printing "Hello, world!" is as simple as writing the name of the procedure.

greetWorld

The same in Ada

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
   procedure Greet_World is
   begin
      Put_Line("Hello, world!");
   end Greet_World;
begin
   Greet_World;
end Hello_World;

Chapter 5: Parameters - Procedures get useful

Let's face it

Procedures as we've seen them aren't terribly useful.  The code we've seen them contain is short, simple and unchanging.  We need to view them in a different light to see their true potential.

The mystical black box

We talk about "black boxes" and what we're really talking about is an interface.  The beauty of an interface is that we know what goes in, what comes out, and any side-effects, but we have no idea how it does that, and what's more, we don't care when we're using the interface.  This frees us, when creating the procedure, to have the inside behave in any way we want.

What is a parameter?

A parameter is an input into a "black box".  It's how we shove information into a procedure.  Let's reconsider our "Hello, world!" program thus far.  As it stands, we only greet this "world" character.  

What if we want to greet anyone?

Well, if we want to be able to greet anyone, then we need to provide their name to the procedure.  This means we need an input.  Let's call it "name", and generalize our procedure to just "greet".

procedure greet (name : string)
   put "Hello, " + name + "!"
end greet

The ": string" is just telling our procedure that this input is going to be a string.  If we try to provide anything else, the program will not run.

The "+" is being used to join two strings.  It's also an integral par of the language.

Now, we can greet... well, let's greet my old buddy Bob.

greet ("Bob")

Read that

No, really, read it out loud.  Isn't it beautiful?  There are no weird, arbitrary programming language words, but rather pure coderspeak.  For something as simple as this, this is perfection.

The same in Ada

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
   procedure Greet(Name : in String) is
   begin
      Put_Line("Hello, " & Name & "!");
   end Greet;
begin
   Greet("Bob");
end Hello_World;

The syntax is a bit different, but the net effect is the same.

Greet("Bob");

This is still beautiful to behold.

Chapter 6: Functions

So, we now have the ability to greet any given Subject or entity.  Still, there's something missing.

Flexibility

We can print "Hello, Bob!" or "Hello, world!", but what if we want to something else with that greeting?

I mentioned earlier that "black boxes" can accept input, cause side-effects, and output information.  We've seen two of those steps.  The "greet" procedure both accepted input and had the side effect of printing a greeting.  However, it didn't output anything.

To accomplish that, at the cost of not being able to cause side-effects, we want a function instead of a procedure.  We'll call our function "greeting", since it will generate the actual greeting, but do nothing in particular with it.

function greeting (name : string) : string
   result "Hello, " + name + "!"
end greeting

Now, to greet my old friend Bob, I can simply "put" the result of the function.

put greeting ("Bob")

This reads just about as well as the previous incarnation, and it's more flexible as well.

The same in Ada

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
   function Greeting(Name : in String) return String is
   begin
      return "Hello, " & Name & "!";
   end Greeting;
begin
   Put_Line(Greeting("Bob"));
end Hello_World;

Chapter 7: Basic Input

It's still inflexible

We can create greetings for anyone we want, but we have no way for the user to put information into the program to change what it outputs.  To avoid creating incredibly boring programs, this is essential.

One thing first

If we're going to have the user input their name, we need a place to store that name.  Such a place is called a "variable".  A variable stores a piece of data which we can then output or manipulate.

Before a variable can be used, though, it has to be declared into existence.  The type of variable we'll be using is a string.  We've seen strings before.  Now we'll just be giving a name to a string.

Declaring a string variable in Turing looks like:

var name : string

Similarly, in Ada95:

Name : String(1 .. 40);

The "1 .. 40" bit specifies the length of the string.

And we're off!

Now, we just need to get the user's name and store it in "name".

Turing:
get name

Ada:
Get_Line(Name, Name_End);

The "Name_End" variable is an integer which the Get_Line procedures stores the length of the string read in.  As a result of needng this extra variable, our declaration should look like:

Name : String;
Name_End : Integer;

Putting it all together

function greeting (name : string) : string
   result "Hello, " + name + "!"
end greeting

var name : string

put "Please input your name:"
get name
put greeting (name)

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
   function Greeting(Name : in String) return String is
   begin
      return "Hello, " & Name & "!";
   end Greeting;
   
   Name : String(1 .. 40);
   Name_End : Integer;
begin
   Put_Line("Please input your name:");
   Get_Line(Name, Name_End);
   Put_Line(Greeting(Name(Name'First .. Name_End)));
end Hello_World;

In summary

We've seen how having the ability to get user input can greatly enhance even the simplest of programs.  

We've also seen how complex Ada appears to be when it comes to strings.

A quick lesson on Ada strings

In Ada a string is just a collection of characters.  When we declare a string, we set aside a certain number of characters worth of space in the computer's memory.  We also give each of those characters a number, starting from one number and counting up to the number of the last character.

Since the first and last numbers can be any numbers we'd like, we can find them with:

String_Variable'First

And:

String_Variable'Last

Getting part of a string (say, everything except the last character) is as simple as:

String_Variable(String_Variable'First .. String_Variable'Last - 1)

Since the Get_Line procedure records the number of the end of the input, we can use this information to get the input string, as in:

Name(Name'First .. Name_End)

Chapter 8: What We've Seen

Basic output

We can print things on the screen.  This is incredibly important, because it allows our program to have results.

Procedures and functions

We can give meaningful names to sets of actions or calculations.  No longer do we have to figure out what a piece of code is doing nearly as frequently.  The name of the procedure or function can give us that information.

Parameters

Parameters give us a way to send information to a procedure to change what it does.  Consider a car analogy: the program is the car.  The engine is a procedure.  The gas pedal is a parameter.  We can change the behavior of the engine based on our gas pedal input.  Push it farther down and the engine revs higher.  Release pressure on the gas pedal and the engine slows down.

Variables

Variables give us a place to store information.  Variables can store any type of information, but they do have a specific type, be it a string of characters or an integer.  We can change what's stored in the variable, and we can provide a variable to a function or procedure as a parameter.

Basic input

We can get string input from the user and store it in a variable.  This means that the user can interact with the program.

Where do we go from here?

The next few chapters will cover some boring, but fundamental concepts required for later chapters to make sense.  There will also be some neat stuff, and further evolution of our "Hello, world!" program.

Chapter 9: A Discriminating Greeter

Where are we?

We've created an elegant means of generating a greeting, which we can output.  We can get a user's name for use in that greeting.  Yet, no matter what the user inputs, we always just say "hello".  It's mean, but let's say we want to laugh at a user if they have a certain name.

If...

The key is to use a conditional to change the output of the "greeting" function depending on the name input.  The basic syntax should be apparent.

function greeting (name : string) : string
   if name = "Clarence" then
      result "Ha... Clarence..."
   elsif name = "Sid" then
      result "Sid?  That's hilarous!"
   else
      result "Hello, " + name + "!"
   end if
end greeting

var name : string

put "Please input your name:"
get name
put greeting (name)

I almost wish it were more complex, so I could offer a lengthier explanation.

with Ada.Text_IO; use Ada.Text_IO;
procedure Hello_World is
   function Greeting(Name : in String) return String is
   begin
      if Name = "Clarence" then
         return "Ha... Clarence...";
      elsif Name = "Sid" then
	 return "Sid?  That's hilarous!";
      else
	 return "Hello, " & Name & "!";
      end if;
   end Greeting;
   
   Name : String(1 .. 40);
   Name_End : Integer;
begin
   Put_Line("Please input your name:");
   Get_Line(Name, Name_End);
   Put_Line(Greeting(Name(Name'First .. Name_End)));
end Hello_World;

More options for comparisons

We've seen the = operator.  It compares two variables to see if they're the same.  We can also determine if two variables are not equal, and test to see if one is greater than the other and vice versa.  Further operators include "greater than or equal to" and "less than or equal to".

Turing:
=, not=, >, >=, =, 