Tinkering with Perl

Own CJS Hayward's complete works in paper!

Table of Contents

Most books you will find on Perl or any other programming language, are books intended to be a one-size-fits-all — or, at least, that's how they're advertised. This book does not attempt or pretend to be appropriate to most users; instead, I am trying to do one thing well.

Well, what am I trying to do? Let me first tell what I am not trying to do:

  • I am not trying to make a book that will be helpful to experienced programmers who want to pick up Perl.
  • I am not trying to make a book that will treat Perl in depth, or for that matter even touch many of the language's strongest points.
  • I am not trying to make a book that will make a novice programmer into an expert programmer overnight.
  • I am not trying to introduce most principles of good software engineering.
  • I am not trying to make a book that promises quick results overnight; I am not trying to make a book that will quickly tell you how to get such-and-such done.

Well, if I am not trying to do all of that, then what am I trying todo?

I wrote this because trying to do this: create a book that would help my brothers learn to tinker.

I first tried to start my brothers straight off with Java. And Java is a ood language — it might have been better for them to know than Perl, and I think it would be a good second language to teach, when they are ready to mature, so that they can produce high quality software. But to learn all of those principles all at once is a heavy load, and one which can be confusing. I was telling them very good things, but I was boring them.

Then I began to think about how I first began to program. I first began to tinker in middle school with BASIC, on Apple ][ series computers. I wrote spaghetti code laced with gotos and all sorts of other things I would shudder to do now. I did not then learn to be a good programmer — at all. But I did learn to be a tinkerer, to play around and explore and put things together. It has been said that education is not the filling of a pail, but the lighting of a fire. That experience lit my fire; it started the curiosity and enjoyment that later caused me to become a more serious programmer.

This book is not an attempt to immediately achieve the end result of a good programmer. It has a goal which might be called more modest, but which might be called much more ambitious: lighting a fire. Once the fire is lit, it can be tended and carefully pruned; there will be plenty of time for the channeling and discipline necessary to let the fire achieve truly great things. I am not trying to do everything; I am trying, for now, to do just one thing. And do it reasonably well.

Chapter Zero: Preliminaries
Unix preliminaries
Directories
pwd
cd
mkdir
ls
Files
Editors
joe
Shebang
Permissions
chmod
Running your programs

Chapter One: Fundamentals
Comments
Variables
Scalars
Lists
Hashes
Statements
Assignment of variables
Assignment of scalars
Arithmetic
Assignment of lists
Assignment of hashes
Input and output
Input
Output
Flow control
Blocks
Conditional clauses
If-then
If-then-else
If-then-else chains
Loops
Foreach loops
While loops
For loops
Subroutines and functions
Arguments
Subroutines
Functions

Chapter two: Sample programs
Friends and pets
Running average

Chapter three: Debugging
Common types of bugs
Syntax errors
Misspelling
Forgotten semicolon
Single and double equals signs

Conclusion

Glossary

Preface

This book has two prefaces: one for a guiding adult, and one for a sharp child who will be exploring the language.

Preface (for children)

When you were younger — perhaps even now — you played or play with Legos, or some other similar building toy. When I was a boy, I played with Legos a lot, and I was very sad when my elaborate collection was destroyed.

Growing up means changing in some ways, but there are also ways in which an adult remains forever a child. It is a truly sad thing when the child inside of a grown-up dies; something important has gone out.

I am a grown-up now, and I still play with Legos. Only now, I play with them in a different form. Instead of using Legos that you can see, I use Legos that you can only see with your mind — I have to use my imagination. I play with these Legos when I program.

When you are holding Legos in your hand, you have in your head an idea of what you want to build. And you start putting the little bricks together, piece by piece, until you have built the thing you've imagined in your head. One little brick is very small and very simple — but there are ways to put them together, and if you put things together the right way, you can do some amazing things.

It is the same way with programming. This book will show you some of the little bricks we have, and then look at ways to put them together. It is my hope that you will begin to tinker — see how you can put things together, see what works, what doesn't work. Then maybe you will imagine things, and see if you can build them out of these programming bricks.

There are many things to learn in programming, and this is only a beginning. But I hope that I may be able to help you begin to explore, and discover what it can be like to program.

Preface (for adults)

Most books you will find on Perl or any other programming language, are books intended to be a one-size-fits-all — or, at least, that's how they're advertised. This book does not attempt or pretend to be appropriate to most users; instead, I am trying to do one thing well.

Well, what am I trying to do? Let me first tell what I am not trying to do:

  • I am not trying to make a book that will be helpful to experienced programmers who want to pick up Perl.
  • I am not trying to make a book that will treat Perl in depth, or for that matter even touch many of the language's strongest points.
  • I am not trying to make a book that will make a novice programmer into an expert programmer overnight.
  • I am not trying to introduce most principles of good software engineering.
  • I am not trying to make a book that promises quick results overnight; I am not trying to make a book that will quickly tell you how to get such-and-such done.

Well, if I am not trying to do all of that, then what am I trying to do?

I am trying to do this: create a book that will help my twelve year old twin brothers learn to tinker.

I first tried to start my little brothers straight off with Java. And Java is a good language — it will probably be better for them to know than Perl, and I think it would be a good second language to teach, when they are ready to mature, so that they can produce high quality software. But to learn all of those principles all at once is a heavy load, and one which can be confusing. I was telling them very good things, but I was boring them.

Then I began to think about how I first began to program. I first began to tinker in middle school with BASIC, on Apple ][ series computers. I wrote spaghetti code laced with gotos and all sorts of other things I would shudder to do now. I did not then learn to be a good programmer — at all. But I did learn to be a tinkerer, to play around and explore and put things together. It has been said that education is not the filling of a pail, but the lighting of a fire. That experience lit my fire; it started the curiosity and enjoyment that later caused me to become a real programmer.

This book is not an attempt to immediately achieve the end result of a good programmer in all regards. It has a goal which might be called more modest, but which I believe is ultimately more important: that of lighting the child's fire. Once the fire is lit, it can be tended and carefully pruned; there will be plenty of time for the channeling and discipline necessary to let the fire achieve truly great things. I am not trying to do everything; I am trying, for now, to do one thing well.

CJS Hayward, 7-16-98

P.S. There are some intentional inaccuracies. This is because a fully technical treatment of the issues involved would, I believe, needlessly confuse children. Some parts are oversimplified; I intend them to be overridden by more nuanced treatments when an appropriate level of intellectual maturity is reached.

Some preliminaries

Here, we aren't (for the most part) really talking about Perl; we're talking about some basics that need to be done in order to use Perl. I will restrict my attention to unix machines. If you use another machine, you will have to read the documentation on your machine.

See also:

Unix preliminaries

Unix preliminaries

Here we will discuss directories, files, editors, permissions, and the famous shebang notation.

See also:

Preliminaries in general - Directories - Files - Editors - Shebang - Permissions

Directories

Directories in Unix are the same as folders on other machines. They're a place to keep files.

There are four basic commands you need to know about directories: pwd, cd, mkdir, and ls.

Directories are stored heirarchically. This means that there's a top level directory, which contains some directories, and each of those directories may contain some files and some directories, and so on. The full name of a direcory is something like this:

/home/jhayward/perl_guide/text/chapter_0/unix

The slashes ('/') tell where we are. The beginning slash indicates the root directory, the top directory of all; home indicates that I'm in the home direcotory in the root directory, jhayward indicates that I am in the directory called jhayward in the home directory (which is my directory to do stuff in), and so on and so forth.

You may refer to a file or directory by its absolute or relative pathname. If you specify its absolute pathname, you give the full path, all the way from the root directory down to where you are now. If you give a relative path, you tell where it is relative to where you are now. The file I am now editing has absolute pathname:

/home/jhayward/perl_guide/text/chapter_0/unix/directories.html

and relative pathname:

directories.html

from where I am now.

The directory .., in a given directory, is the directory one level up. So the directory

/home/jhayward/perl_guide/text/chapter_0/unix/..

is the same as the directory

/home/jhayward/perl_guide/text/chapter_0/

See also:

pwd - cd - mkdir - ls - Files

pwd

pwd is a Unix command that means print working directory. It prints the directory you're in now. If you're logged in to a Unix machine, why don't you type pwd (and hit return) to see what happens?

You can use pwd to see where you are; make sure you're in the right directory.

See also:

Unix preliminaries - Directories - cd - mkdir

cd

cd is a Unix command which means change directory. It changes the directory you are in to another one.

In general, you can type:

cd pathname

where pathname is the absolute or relative pathname (as discussed before) of the directory. For example, to go to the parent directory (the directory one level above) for your current working directory, you can type:

cd ..

What do you think will be the result of typing in the following commands:

pwd
cd ..
pwd

Why don't you type them in, and see what happens?

Finally, as a special case, if you type

cd

without anything else after it, it will take you to your home directory. Your home directory is the directory you are given on the computer to do things in.

See also:

Unix preliminaries - Directories - pwd - mkdir

mkdir

mkdir is the command to make a directory. We will probably be making files as we tinker; let's create a directory for those files.

First, go to your home directory:

cd

Then make a directory — say, one called tinkering.

mkdir tinkering

Now, we should go into that directory before doing most of the other things suggested in this book. So go into that directory:

cd tinkering

Remember to go to that directory before each time you start reading this book. If you're not sure what directory you're in, you can always type

pwd

to find out what directory you're in. From any place in the system, you can type in the following to go to your tinkering directory:

cd
cd tinkering

Now we're ready to talk about files and editors.

See also:

Unix preliminaries - Directories - pwd - cd - ls

ls

ls is the Unix command to list the files in a directory. To see what files and directories are in your current directory, type:

ls

You may not see anything — if you are following this book in order, you should be in an empty directory. Keep this command in mind, though; it should come in handy in the future.

See also:

Unix preliminaries - Directories - pwd - cd - mkdir - Files - Editors

Files

A directory is a place to keep things on a computer; a file is what sort of thing you actually keep. We are going to be interested in creating, and modifying, Perl programs.

A file should have a name consisting of letters, numbers, and/or underscores. Perl programs should end by having ".pl" added to the end. Here are some examples of good filenames:

hello_world.pl
test.pl
list_pets.pl

Each file (of the sort we're working with) will hold one program, and (for now) each program will be stored in one file. So a file is where you store a program. You will create these programs with editors, and then make them usable by setting the permissions.

See also:

Unix preliminaries - Directories - ls - Editors - Permissions

Editors

Editors are programs that can be used to create and change files. In our case, we are interested in text editors, which are specifically for editing filies that contain text.

There are a number of different editors, each of which has its own strengths and weaknesses. For now, I will have you use an easy-to-use editor called joe.

See also:

Unix preliminaries - Files - joe

joe

joe is the name of an easy to use editor for Unix systems. To use joe to create a file called hello_world.pl, type:

joe hello_world.pl

You will now see a screen that is mostly blank. Type control-K and then 'H' to get a help screen. That will bring up on the screen most of the commands you need to know to edit files.

We are going to create our very own program. Type in the following, exactly as you see it on the screen:

#!/usr/local/bin/perl

print "Hello world!\n";

Then type control-K and X to save the file. It will ask you what file to save it as; type:

hello_world.pl

Keep reading to find out how to run the program.

See also:

Unix preliminaries - Files - Editors - Shebang - Permissions

ShebangIn Unix, the characters "#!" at the beginning of a file tell the computer what program to use to figure out what to do with it. This is referred to as the shebang notation.

In order to tell the computer that your files are Perl programs, you should put the following line at the beginning of every Perl program, exactly as it is typed here:

#!/usr/local/bin/perl -w

or

#!/usr/bin/perl -w

(Which one should you use? One of them will work, and the other won't. Try it.)

If you don't do that, the computer will be very confused when you tell it to run your programs.

See also:

Unix preliminaries - Files - Editors - Permissions

Permissions

When you create a text file, Unix doesn't normally expect that you're going to run it like a program. So, you have to tell it that you're giving yourself and perhaps others permission to run them as programs.

This is accomplished with the chmod command.

See also:

Unix preliminaries - Files - chmod

chmod

chmod is the Unix command used to set permissions, including telling the computer that a file can be run as a program.

To make it so that everybody can use a program, type:

chmod 755 filename

where filename is the name of the file, which should be something like "hello_world.pl".

Alternately, to make it so that only you can use the program, type:

chmod 700 filename

You must do this before you can run a program. If you've been following along this book in order, please type:

chmod 755 hello_world.pl

And now, you're ready to run it!

See also:

Preliminaries - Files - Permissions

Running your programs

If you've been following along the text in order, you have created a program, and made it executable (runnable). Now, you can run it:

hello_world.pl

What happened? Did it print out, "Hello, world?" If so, great! If not, you probably made a little mistake somewhere — as has every programmer, great or small — and you need to go back and see what happened.

See also:

Unix preliminaries - Files - Shebang - Permissions

Fundamentals

This chapter introduces the basic building blocks you will combine and fit together to make programs.

Comments

When you are writing a program, you are writing for people as well as computers. Most of the time, after a program is written, you or someone else will want to make changes — to add new features, or to fix bugs. There is a joke which my father likes to tell:

A construction worker, at lunch break, opens his lunchbox, and says, "Salami again! I hate bologna!"

Then, the next day, he says, "I wonder what I have today." He opens his lunchbox, and says, "Bologna again? I hate bologna!"

This continues for a week. Finally, one of his coworkers says, "Why don't you ask your wife to give you something else for lunch? That way, you wouldn't have to have bologna all the time."

The construction worker says, "Oh, I don't have a wife. I make my own lunches!"

In this joke, the construction worker eats the sandwiches he hates because that's what he made earlier. This joke is a lot like programming. The construction worker is like a programmer, and the yucky bologna sandwiches are programs that don't have very many little notes, in English, to explain things. It can be very difficult, even for experienced programmers, to figure out or remember what a program is doing if it doesn't have notes to explain things. These little notes are called comments, and you can say anything you like in a comment. (But we generally use comments to explain programs.)

Comments are done differently in different computer languages, but there is some feature that tells the computer what is a comment and what is the rest of the program. In perl, a comment begins with a hash mark ('#'), and continues to the end of the line. If you want to make a comment that uses more than one line, put a hash mark on a second line. Here are some examples of what is and is not a comment:

# This is a comment.

# This is a comment, which
# uses more than one line.

#
# This is a comment, too.  It uses blank lines to make
# things better to look at.
#

                # This is a comment which begins in the
		# middle of a line.  You can put a
		# comment to the right of something 
		# else, to explain what it does.

This is not a comment.

The comment begins #here.

See also:

Statements

Variables

In school, you may have used variables to refer to different numbers. The variables x could be 3, or 4, or 0, or -9.5. One variable can mean any of several different numbers. (But it can only mean one thing at a time.)

In computer programming, we use variables to represent all sorts of different things. In Perl, there are three different types of variables we will use: scalars, lists, and hashes. The names sound a little funny, but don't let that scare you.

See also:

Scalars - Lists - Hashes - Assignment of variables in general

Scalars

A scalar is a variable that can either refer to a number, or some text, which is called a string. A string is usually enclosed in quotes, like this:

"This is a string."

Note that the quotes are not actually part of the string; they are put around the string to tell when the string begins and ends.

You can give a variable almost any name that you can make from letters, numbers, and underscores ('_'). Furthermore, you must put a dollar sign ('$') before a scalar to tell Perl that it is a scalar.

In general, it is a good idea to have a variable name consist of a few words that describe what the variable tells you. There are a couple of ways people have of putting words together. (You have to do something to tell when one word ends and the next begins, because itishardtoreadwhenyoucan'tseparatewords.) One way is to capitalize the first letter of each word; another is to separate words using underscores ('_'). It doesn't matter which way you do it, but you should pick one way and stick with it. It is very important that you spell a variable exactly the same way every time you use it; otherwise, the computer will think you are using different variables. Here are some examples of good variable names:

$NumberOfTrucks
$AverageHeight
$PlayerName

Or, if you prefer underscores, then you can do it this way:

$number_of_trucks
$average_height
$player_name

In this book, I will always do it the first way.

See also:

Variables - Lists - Hashes - Assignment of variables in general - Assignment of scalars - Arithmetic

Lists

A list is a variable that lets you keep track of several things. If you were shopping for groceries, you'd keep a list: apples, ketchup, bread, sausage, and so on. A list is a variable that keeps track of several things, instead of just one. A list is named like a scalar, but instead of having a dollar sign ('$') in front of the name, we place an atgry ('@'). A good name for a list would be something like:

@GroceriesToBuy

See also:

Variables in general - Scalars - Hashes - Assignment of variables in general - Assignment of lists

Hashes

Hashes are a little more complicated than either lists or scalars, but they are very useful.

Let's say that you know some people, and you want to keep track of what kind of pets they have. Suppose that you know John, Sue, and Mary. Let's also suppose that John has a dog, Sue has a cat, and Mary has a goldfish. What would be good would be a single variable, called Pet: if you plugged in John, you would get dog; if you plugged in Sue, you would get cat; if you plugged in Mary, you would get goldfish.

A hash is a variable that can do that. We refer to a hash in slightly different ways, depending on what you want to do. If you refer to the whole hash, you put a percent sign ('%') in front of the hash. So the hash with the pets might be:

%pet

But if you want to refer to a specific pet — say, you want to find out what pet Mary has — you would do it like this:

$pet{"Mary"}

(We put the "Mary" in quotes, because it is a string, and the computer will get confused if it sees the letters M, a, r, and y all by themselves.)The expression

$pet{"Mary"}

should be read as, "Mary's pet".

See also:

Variables in general - Scalars - Lists - Assignment of variables - Assignment of hashes

Statements

Let's say that you are going to play at a friend's house. What you might do, could be explained as a list of activities:

Ask your parents for permission to visit your friend.
Call your friend's house, and ask permission to come over.
Finish getting dressed.
Walk over to your friend's house.
Take chewing gumm off of your shoe.
Greet your friend.
Play with your friend.
Eat a snack.
Play some more.
Say goodbye.
Walk home.
Take off your shoes.

What we have done here, is to break one bigger activity (visiting your activity) into a sequence of smaller activities. Another way of putting it is that we are explaining how to visit your friend by saying what smaller things are necessary to visit your friend.

When you are programming a computer, you do the same thing. The little commands are called statements. A statement is a command that tells a computer to do something small, as a part of doing something larger. (Saying to walk to your friend's house, when you are explaining how to visit your friend, is like a statement.)

As we work further, we will learn more about different kinds of statements. But first, let's make sure that we understand what a statement is: a statement is an individual command you give to the computer, as part of telling it how to do something. In the description of how to visit a friend's house, each line, like "Greet your friend," or "Remove chewing gum from your shoe," is like a statement. The whole list, all together, is like a program.

One final note about statements: In English, you usually end a sentence with a period ('.'). In Perl and many other computer languages, you end most statements with a semicolon (';'). For example:

This sentence ends like a statement;

See also:

Assignment of variables - Input and output - Blocks - If-then - Loops - Subroutines

Assignment of variablesIn math class, with a story problem, your teacher might have said something like this: "Suppose we have five cats..." What is going on here is that we have some number of cats, and we are saying that the number of cats is specifically equal to five.

Another way of saying what the teacher said is,

Let the number of cats be five.

We can use a variable for the number of cats. Let's put a variable in there:

Let NumberOfCats be five.

Or, to say it a little differently,

Let NumberOfCats equal five.

With computers, we drop the 'let', even though it's understood.

NumberOfCats equals five.

(Now, we are not simply claiming that the number of cats equals five. We are commanding that it be so.)

Finally, in Perl, we use an equals sign ('=') when we mean "equals", and we use numerals: we write '5' instead of "five". And remember — most statements end with a semicolon, and we put a dollar sign ('$') in front of scalars. So let's change the period into a semicolon, and put a dollar sign in front of the variable:

$NumberOfCats = 5;

And that's how we do it in Perl. We have just assigned the variable NumberOfCats a value of five.

We can also assign a variable to other things. For example, if we know the number of cats, and we know the total number of cats and dogs, we can find out the number of dogs by subtracting. If we have thirteen cats and dogs total, and five cats, then here is how we can get the number of dogs:

$NumberOfCats = 5;
$NumberOfCatsAndDogs = 13;
$NumberOfDogs = $NumberOfCatsAndDogs - $NumberOfCats;

The computer has done the subtracting for you, and figured out the answer.

Note: In an assignment, there is one variable on the left side of the equals sign, which is changed. Nothing on the right side (unless it is also on the left side, which will be discussed later) is changed.

See also:

Statements - Assignment of scalars - Assignment of lists - Arithmetic - Functions

Assignment of scalars

There are a few ways to assign a scalar. You can assign a scalar to a given value:

$NumberOfCats = 5;
$MyCatsName = "Zappy";

Or you can assign one variable using another:

$NumberOfNoses = $NumberOfPeople;

This tells the computer that the number of noses is the same as the number of people. Or, to put it another way, it takes the value stored in the variable NumberOfPeople, and stores a copy of it in $NumberOfNoses.

There are several things that you can do with a string. One useful thing you can do is concatenate two strings. For example, if you concatenate the strings "My cat's name" and " is Zappy.", you get, "My cat's name is Zappy."

Did you notice the space between the quotation mark and the "is"? That space is important. Computers don't know when you should add a space to separate words. If you concatenate "My cat's name" and "is Zappy." without the extra space, it would come out, "My cat's nameis Zappy."

In Perl, you can concatenate two strings by putting a period ('.') between them. For example, you could get the whole sentence like so:

$WholeSentence = "My cat's name" . " is Zappy.";

Or, to do it differently,

$FirstPartOfSentence = "My cat's name";
$SecondPartOfSentence = "is Zappy.";
$WholeSentence = $FirstPartOfSentence . " " . $SecondPartOfSentence;

Do you see what I did here? I didn't have a space before "is" in SecondPartOfSentence, but I put another space in between the two parts. There were three strings here: $FirstPartOfSentence, " " (a string consisting of only a space), and $SecondPartOfSentence. I concatenated all of them together, just as you add 3 + 1 + 2 to get 6. Putting in an extra space can come in handy, when you want to make text look good.

There are other ways to assign scalars, and they will be covered when we discuss arithmetic and functions.

See also:

Variables in general - Scalars - Statements - Assignment of variables in general - Arithmetic - Assignment of lists - Assignment of hashes - Functions

Arithmetic

Perl, like many languages, lets you do arithmetic with numbers. You can have a statement like

$Average = ($FirstNumber + $SecondNumber + $ThirdNumber) / 3;

and the computer will do the arithmetic for you. It will add the three numbers, and divide the result by three. The result is stored in Average.

You may have noticed that I had parentheses — why are they necessary? This has to do with something called order of operations. Let's say we want to figure out what 3 * 4 + 5 equals. Well, what do you do first — multiply 3 by four, or add 4 and 5? If you multiply first, then 3 * 4 = 12, so you have 12 + 5, or 17. So the expression equals 17. But what if you add first? Then 4 + 5 = 9, and 3 * 9 = 27, so we have 27. The number you get depends what you do first.

Parentheses are a way to tell the computer what to do first. Everything inside a pair of parentheses is calculated before everything outside of the pair of parentheses. Everything on an inside pair of parentheses is calculated before things on an outside pair of parentheses. So, for example, if we have (((3 * 4) + 6) / 9), that means that we first multiply 3 * 4 = 12, to get ((12 + 6) / 9); then we add 12 + 6 = 18, so we get (18 / 9), and then we divide 18 / 9 = 2, so we get a result of 2.

At least for now, you should always use parentheses to tell the computer what it should do first. Use parentheses, so that the computer knows exactly what order you want it to do things in.

Two notes:

First, if you ask it to do something that's going to give a fraction (like "What is five divided by three?"), it will give a decimal for an answer. Usually, if there is a decimal involved in a calculation, the result will be a decimal. (With decimals, an answer will usually be a little more or a little less than it should be. That is a kind of error that happens with computers.)

Second, you can't divide by zero. If you try to divide by zero, your program will stop running. It is good practice, before dividing by a variable, to make sure that it is not zero (see if-then).

It is generally good, when doing arithmetic calculations, to break them into as many small steps as possible. It is better to have several simple calculations than one really long and confusing one.

See also:

Scalars - Assignment of scalars - Conditional clauses - If-then

Assignment of lists

There are a few ways to assign a list. One way is like this:

@MyFriends = ("John", "Susan", "Mary");

The list is assigned to something described by a left parenthesis ('('), some scalars separated by commas (','), a right parenthesis (')'), and then the semicolon (';'). You can use variables and numbers as well as just strings, like this:

@Numbers = ($LastNumber, 9);

You can also put everything that's in one list, into another list. For example, you might write:

@PeopleIKnow = (@MyFamily, @MyFriends, "Jane", "Bob");

Then the list of people you know includes everybody in the lists of your family and friends, plus Jane and Bob.

One thing you will do often is to add one element to a list. Suppose you have a new friend named Fred, and you want to add him to your list of friends. You could do it this way:

@MyFriends = (@MyFriends, "Fred");

Now, I would like to answer a question you may have == how can MyFriends be equal to itself plus "Fred" added on to the end? That is like saying that a number equals itself plus one.

The answer is that the statement should be read like this: "Let the new value of MyFriends equal the old value of MyFriends, with "Fred" added at the end. It is possible, and useful at times, to use one variable on both sides of the equals sign ('=') in this way.

See also:

Variables in general - Lists - Statements - Assignment of variables in general - Assignment of scalars - Assignment of hashes - Functions

Assignment of hashes

Hashes may be assigned one of two ways: one of which remembles a scalar, and the other of which is like the assignment of a list.

Recall the earlier example where John, Sue, and Mary have a dog, a cat, and a goldfish respectively. The easiest way, and the one you should probably use most of the time (until you've outgrown this book), is to say, "John's pet is a dog. Sue's pet is a cat. Mary's pet is a goldfish." In Perl, we write it this way:

$Pet{"John"} = "dog";
$Pet{"Sue"} = "cat";
$Pet{"Mary"} = "goldfish";

Remember that $Pet{"John"} should be read as "John's pet." This means that the whole statement should be read, "Let John's pet be a dog." Even though the computer statement looks rather funny, it really says something that is fairly close to English.

The second way makes a bunch of assignments at once — it is useful when you want to create a hash from scratch. Creating the same hash this way would look like this:

%Pet = ("John" => "dog",
	"Sue"  => "cat",
	"Mary" => "goldfish");

Now, did you notice that the statement was broken over a few lines? It's OK to split a statement over several lines and put spaces in to format it; indeed, it is good to do so. It makes the code more readable. This is called spacing.

See also:

Variables in general - Hashes - Statements - Assignment of variables in general - Assignment of scalars - Assignment of lists - Functions

Input and output

One important thing for programs to be able to do, is to be able to pay attention to what people say to them, and say things to people.

There are varying ways that programs do this; here, I will address a couple of the simpler ways. They both involve the keyboard. One reads a line in from the keyboard to a variable — that is, it reads in everything the user types, until he hits return — and the other prints out some specific text.

See also:

Statements - Input - Output

Input

The way I'm going to teach to do input, is as follows: Say that you want to input some line of text from the user, and store the result in the variable $UserResponse. The following two lines will accomplish that:

$UserResponse = <>;
chomp $UserResponse;

The first line reads a line into $UserResponse. But that includes the return character at the end of the line, which we generally don't need. The second line takes the extra character off.

In general, you should use something like these two lines when you want to input a line from the user.

See also:

Statements - Scalars - Input and Output - Output

Output

The print statement is useful for output. Let me give an example of a very famous program:

#!/usr/local/bin/perl
print "Hello, world!\n";

The first line is a line you should put at the beginning of every Perl program you write. The second line prints, "Hello, world!" It is the second line we are studying.

What's that funny "\n"? What does it mean? Well, Perl doesn't know by itself when a line should end. So, we put "\n" at the end of each line, to tell it to go to the next line.

Here is another example of some code using print:

print "The average is " . $Average . ".\n";

Now, what does that all mean?

Remember that, earlier, when we talked about scalars, we could concatenate two strings by putting a period ('.') between them. This takes three strings: "The average is ", $Average, and ".\n", and sticks them all together. Let's say that $Average is 4.5. Then the result will look like:

The average is 4.5.

The "." in ".\n" is just a period for the end of the sentence, and "\n" means the end of line.

See also:

Statements - Scalars - Input and output - Input

Flow control

In many programming languages, there is a very powerful kind of statement called the goto statement. Quite often in programming, you are at one part of your code, the list of instructions, and you need to be somewhere else. So programmers would just put a goto in, and voila! you were at that other part of the program.

Well, gotos are very powerful, but they have a bit of a problem with them. If you just use gotos in the way that comes most naturally, the result is something called spaghetti code: the program just goes in and out in one tangled mess that's impossible to understand, just like spaghetti. This results in code that's full of bugs, that's impossible to fix.

Therefore, it is in most cases strongly discouraged to use gotos. Gotos are considered hazardous to your health, and many programmers consider 'goto' to almost be a dirty word.

But wait. A goto is very powerful. If we're going to say "no gotos", shouldn't there be something else to replace them?

And the answer, fortunately, is "Yes." There are other ways to do almost anything that you would do with a goto — but do it better, and more cleanly. These ways make things much easier to understand, and have less bugs. The bugs that do get in are easier to fix.

There are two basic kinds of structures, that can do almost all of the work done with gotos — but do it much better. These two structures are called conditionals and loops, and we will explore them. There are also subroutines and functions, which will be covered later, and are also very powerful.

See also:

Statements - Blocks - If-then - If-then-else - If-then-else chains - Loops - Foreach loops - While loops - For loops

BlocksFor both conditionals and loops, it is useful to think of a cluster of statements taken together. A block of code begins with a left curly brace ('{'), and ends with a right curly brace ('}'). It should also be indented (have a margin on the left) by two to four spaces. It doesn't matter how far you indent, but you should indent to the same depth most of the time. Here are a few statements by themselves:

print "Type something in: "; # The lack of a \n is intentional, so that the
                             # cursor stays on the same line.
$UserInput = <>;
chomp $UserInput;
print "You typed in " . $UserInput . ".\n";

Here is that same group of statements in a block:

    {
    print "Type something in: "; # The lack of a \n is intentional, so that
				 # the cursor stays on the same line.
    $UserInput = <>;
    chomp $UserInput;
    print "You typed in " . $UserInput . ".\n";
    }

In short, to make a block, you put a left curly brace before it, type in the statements in the block, and close with a right curly brace. The whole thing should be indented four spaces.

See also:

Statements - Flow control - If-then - If-then-else - If-then-else chains - Loops - Foreach loops - While loops - For loops - Functions

Conditional clauses

A conditional clause is something that is either true or false. The computer needs to be able to decide if something is true or false.

There are a number of different types of conditional clauses. The one which I will cover here, to get started with, is equals. An expression like:

($UserResponse == "y")

is an example of a conditional clause.

You can build up conditional clauses by using and, or, and not, as well as parentheses. Here is an example of a more complicated clause:

(($MyPet == "dog") || ($MyPet == "cat"))

You should always use lots of parentheses with conditionals, just like you should use parentheses in arithmetic. Furthermore, the parentheses have more or less the same meaning.

Now, I can see a question. Why did I use two equals signs instead of one? The answer is that Perl uses one equals sign for assignment, and two equals signs for conditionals. If you use one equals sign, Perl will think you are doing an assignment. For example, if you type:

($UserResponse = "y")

what that will do is assign $UserResponse the value "y", instead of checking to see if $UserResponse is already "y". This is a very easy mistake to make; check for this when your program seems not to work.

If-then clauses, and loops, do different things depending on whether something is true. A conditional clause is something that can be true or false, which Perl can use to decide if something is true, and therefore run if-thens and loops.

Scalars can also serve as conditional clauses. A scalar that has a value of 0, or that is an empty string (i.e. a string that doesn't contain any characters, not even spaces — it would be represented as ""), is considered false. Any other scalar is considered true. In general, we use a 1 to represent true, and a 0 to represent false.

Note: Conditional clauses don't have semicolons after them.

See also:

Statements - Arithmetic - Flow control - Blocks - If-then - If-then-else - If-then-else chains

If-then

Remember, back when we introduced statements, how we talked about going to a friend's house? Let me reproduce the list of what to do:

Ask your parents for permission to visit your friend.
Call your friend's house, and ask permission to come over.
Finish getting dressed.
Walk over to your friend's house.
Take chewing gumm off of your shoe.
Greet your friend.
Play with your friend.
Eat a snack.
Play some more.
Say goodbye.
Walk home.
Take off your shoes.

Well, this list didn't involve any decisions — and there are decisions involved. For example, you only continue over to your friend's house if you get permission, right?

Let's rewrite the list using if-then logic:

Ask your parents for permission to visit your friend.
If your parents give permission to visit your friend:
    {
    Call your friend's house, and ask permission to come over.
    If your friend's parents give permission to come over:
	{
	Finish getting dressed.
	Walk over to your friend's house.
	If you stepped on some chewing gum:
	    {
	    Take chewing gumm off of your shoe.
	    }
	Greet your friend.
	Play with your friend.
	Eat a snack.
	Play some more.
	Say goodbye.
	Walk home.
	Take off your shoes.
	}
    }

What we have here is a modified list of how to visit your friend, that only does things if they are appropriate — for example, it only goes over to your friend's house if you have permission to go over.

The syntax in Perl for this sort of thing is as follows:

if (condition)
    {
    code to execute if condition is true
    }

"if" must be spelled exactly that way, with a lowercase 'i', and the curly braces put around the code to be executed. What Perl will do when it sees that, is see if the conditional clause is true, and if so, execute the block that's inside the braces.

See also:

Statements - Flow control - Blocks - Conditional clauses - If-then-else - If-then-else chains

If-then-elseSuppose that I want to do something in a programming language. Some pseudocode might be as follows:

if (I know how to do it)
    {
    do it;
    }
else
    {
    try to find out how to do it;
    }

There is one thing I want to do if the conditional clause is true, and another thing to do if the conditional clause is false. And that is done with this exact syntax:

if (conditional clause)
    {
    block of code to execute if the conditional clause is true
    }
else
    {
    block of code to execute if the conditional clause is false
    }

See also:

Statements - Arithmetic - Flow control - Blocks - Conditional clauses - If-then - If-then-else chains

If-then-else chainsThere is one more step to be taken with if-then-else. That is demonstrated by the following segment of code:

if ($Pet == "dog")
    {
    print "Arf, arf!\n";
    }
elsif ($Pet == "cat")
    {
    print "Purr, purr!\n";
    }
elsif ($Pet == "goldfish")
    {
    print "Splish, splash!\n";
    }
else
    {
    print "I don't know what sound the pet makes.\n";
    }

Sometimes, you have more than two choices to deal with — there are more than two (or three) possibilities for a pet. An if-then-else chain is ideal for the following; the program checks if the first condition is true, and if the first condition is false, it checks if the second condition is true, and so on and so forth. The general syntax is:

if (first conditional clause)
    {
    code to be executed
    if first conditional clause is true
    }
elsif (second conditional clause)
    {
    code to be executed if first
    conditional clause is false, but
    second conditional clause is true
    }
...
elsif (last conditional clause)
    {
    code to be executed if all but the
    last conditional clauses are false, but
    the last conditional clause is true
    }
else
    {
    code to be executed if none of the
    conditional clauses are true.
    }

The final else is optional, but recommended.

See also:

Statements - Arithmetic - Flow control - Blocks - Conditional clauses - If-then - If-then-else

Loops

A loop is what is executed when you want to run the same code for several different things. For example, here is some pseudocode to get bundled up in the winter:

while (there is more clothing to put on)
    {
    Select another item of clothing to put on.
    Pick it up.
    Put it on.
    }

There are different types of loops for different purposes.

See also:

Statements - Flow control - Conditional clauses - Foreach loops - While loops - For loops

Foreach loops

One useful kind of loop, does something to each element of a list. For example, here is how might might code getting bundled up to go outside in the winter to go sledding:

@WinterClothing = ("coat", "snowpants", "boots", "gloves", "scarf", "hat");
foreach $ArticleOfClothing (@WinterClothing)
    {
    print "I'm putting on my $ArticleOfClothing.\n";
    }

Before dissecting exactly how this loop works, let me show you what it does. It prints out:

I'm putting on my coat.
I'm putting on my snowpants.
I'm putting on my boots.
I'm putting on my gloves.
I'm putting on my scarf.
I'm putting on my hat.

There are a couple of things going on here.

First, we assign a list.

Then we go through the loop several times — each time, the variable $ArticleOfClothing is set to equal a different element of @WinterClothing, and the block of code is executed.

In that code, when Perl sees $ArticleOfClothing, it substitutes the value of $ArticleOfClothing (which may be "coat", "snowpants", etc.) for the name of the variable. So, the first time through, "I'm putting on my $ArticleOfClothing.\n" becomes "I'm putting on my coat.\n", where "\n" tells Perl that that's the end of the line.

Foreach loops should be used when you want to do something with every element of a list.

See also:

Statements - Lists - Flow control - Blocks - Loops - While loops - For loops

While loopsA while loop is a loop used to run a block of code while a condition is true. For example:

$ShouldContinue = "y";
$NumberOfTimesThroughLoop = 0;
while (not($ShouldContinue == "n"))
    {
    ++$NumberOfTimesThroughLoop;
    if ($NumberOfTimesThroughLoop == 1)
	{
	print "This loop has been executed $NumberOfTimesThroughLoop time.\n";
	}
    else
	{
	print "This loop has been executed $NumberOfTimesThroughLoop times.\n";
	}
    print "Go through the loop again(y/n)? ";
    $ShouldContinue = <>;
    chomp $ShouldContinue;
    }

Now, let's look at what this code does.

$ShouldContinue tells if the loop should continue. "n", for no, means to stop; anything else means to continue. So the loop says, "While we should continue".

The variable $NumberOfTimesThroughLoop is initialized to 0 (set up to be equal to 0) before the loop begins. Then the first thing inside the loop, "++$NumberOfTimesThroughLoop;", means to increase the value of $NumberOfTimesThroughLoop by one. In general, the expression:

++$variable name;

where variable name is the name of a "scalar" variable, means "Increase the value of variable name by one."

Then we have a conditional. This conditional sees if it's the first time through the loop. Why do we do that?

The statements inside the if clause (the block immediately following the if) and the else clause are almost identical — but there is an 's' after "time" in the else clause. This is so that, on the first time through, the program will print out:

This loop has been executed 1 time.

but on the second (third, fourth, etc.) time through, it will say something like:

This loop has been executed 2 times.

Then, after that, it asks the user if he wants to run through the loop again. After doing that, it reads a line of input into the variable $ShouldContinue — if the user types "y", $ShouldContinue will contain a "y", and if the user types "n", $ShouldContinue will contain a "n".

Then, after that, it checks if it should continue (the conditional clause right after the word "while"), and if it should, it executes the loop again.

See also:Statements - Flow control - Blocks - Conditional clauses - If-then-else - Loops - Foreach loops - For loops

For loops

A for loop is a special case of a while loop, which is commonly used for doing something a certain number of times.

Let's suppose that I wanted to print "Hello, world!" ten times. I could just have ten lines like so:

print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";
print "Hello, world!\n";

But what if I wanted to change the number — to five or to fifty? It would take a lot of editing.

There's a better way to do it, though. I could have the computer count up to ten, and each time print out "Hello, world!". If I did that, then changing it to five or fifty would only mean changing the number I have to count to.

Let me give some code to do that, and explain what it does.

for($CurrentLine = 0; $CurrentLine < 10; ++$CurrentLine)
    {
    print "Hello, world!\n";
    }

That's all the code that it takes. And what if I wanted to print "Hello, world!" a thousand times? A very easy change — only change the 10 to 1000:

for($CurrentLine = 0; $CurrentLine < 1000; ++$CurrentLine)
    {
    print "Hello, world!\n";
    }

Now, let me explain what it does. Let's look at the first line. It has the following format:

for(part one; part two; part three)

It has three parts, separated by semicolons (';'). Each part does something different.

The first part is run exactly once. It is used to set things up — in this case, to assign the scalar variable the value of zero.

For reasons that you will understand later when you program, you should have computers start counting at 0. So, instead of counting from 1 to 10, this counts from 0 to 9 — and still does it ten times.

The second part is the conditional clause that is tested each time you run through the loop. In this case, it makes an arithmetic assertion: that CurrentLine is less than 10. After running through the loop, the computer checks to see if the second part is still true — if it's true, the computer runs through the loop one more time.

The third part is something the computer does each time, after running through the loop and before checking the conditional clause. In this case, it increments (adds one to) the value of $CurrentLine.

So, all together, we have the computer counting from 0 to 9, and each time printing out a "Hello world!" message.

See also:

Statements - Scalars - Assignment of scalars - Arithmetic - Flow control - Blocks - Conditional clauses - Loops - Foreach loops - While loops

Subroutines and functions

When you learned to walk, it was a bit tough to learn — but once you had learned once, you learned a way of walking that would take you anywhere (within certain bounds), on any kind of surface (within other bounds). You had learned walking in general, and so you didn't need to learn to walk each time you met something new.

For computers, there are many things you'll want to do a number of different times, in a number of different places — but it's really only one thing. With subroutines and functions, you can write miniature programs that do one thing — and then you have a new command that is available to you, taking only one line, whenever you want to do something.

Subroutines are powerful. Subroutines are good. Whenever you find yourself doing the same thing in more than one place, it is probably good to put it in its own subroutine.

See also:

Variables - Statements - FLow control - Blocks - Arguments - Subroutines - Functions

ArgumentsSome subroutines and functions need information to do their job. For example, you might have a subroutine to tell the price for so many apples, so many oranges, and so many bananas — but first you need to tell it how many apples, oranges, and bananas there are, so it can calculate them!

That is done by giving the subroutine or function some arguments. The way you use a subroutine/function is to give an ampersand ('&') before the name of the subroutine/function, then its name, and then a list of arguments. For example, if we used the subroutine I mentioned, you might invoke it like this:

&TellPrice($NumberOfApples, $NumberOfOranges, $NumberOfBananas);

We'll see exactly how to write such a subroutine here.

See also:

Variables - Scalars - Lists - Flow control - Subroutines and functions - Subroutines - Functions

Subroutines

A subroutine is a miniature program that you can run from within your program. Earlier, we talked about a procedure that would tell a price for an amount of fruit. Here is how we write such a procedure. Before the procedure is used, we assume that there is some code that tells the price of the different kinds of fruit:

$PricePerApple = .25;
$PricePerOrange = .30;
$PricePerBanana = .20;

And here is the subroutine itself:

sub TellPrice()
    {
    $NumberOfApples = shift(@_);
    $NumberOfOranges = shift(@_);
    $NumberOfBananas = shift(@_);
    @RemainingArguments = @_;
    $PriceForApples = $NumberOfApples * $PricePerApple;
    $PriceForOranges = $NumberOfOranges * $PricePerOrange;
    $PriceForBananas = $NumberOfBananas * $PricePerBanana;
    $TotalPrice = $PriceForApples + $PriceForOranges + $PriceForBananas;
    print "The total price for the fruit is $TotalPrice.\n";
    }

Well, let's look at it piece by piece:

    $NumberOfApples = shift(@_);
    $NumberOfOranges = shift(@_);
    $NumberOfBananas = shift(@_);
    @RemainingArguments = @_;

This part finds out what the arguments to the procedure are, and stores them in the appropriate variables. This should go at the beginning of the subroutine; the syntax for using the subroutine is:

&TellPrice($NumberOfApples, $NumberOfOranges, $NumberOfBananas);

The part of the subroutine that gets the arguments should be of the following form:

    $first argument = shift(@_);
    $second argument = shift(@_);
    $third argument = shift(@_);
    ...
    @RemainingArguments = @_;

where first argument, second argument, and so on are the names of the arguments in order.

After firuging out what the arguments are, the subroutine then does some arithmetic to figure out the total price, and prints it out.

One more thing... At the beginning of the program, you need to declare your subroutine, by having a line like this:

sub &TellPrice();

See also:

Statements - Flow control - Blocks - Subroutines and functions - Arguments - Functions

Functions

One kind of useful subroutine is one that does some calculations, or something like that, and gives a value as an answer. For example, suppose we wanted to be able to assign the total price to a variable in our fruit market example. This is what functions are for.

To use a function, we would do something like this:

$TotalPrice = &CalculatePrice($NumberOfApples, $NumberOfOranges,
  $NumberOfBananas);

And the CalculatePrice function is almost exactly the same as the TellPrice procedure. Here is its listing, with all of the changes in bold:

sub CalculatePrice()
    {
    $NumberOfApples = shift(@_);
    $NumberOfOranges = shift(@_);
    $NumberOfBananas = shift(@_);
    @RemainingArguments = @_; 
    $PriceForApples = $NumberOfApples * $PricePerApple;
    $PriceForOranges = $NumberOfOranges * $PricePerOrange;
    $PriceForBananas = $NumberOfBananas * $PricePerBanana;
    $TotalPrice = $PriceForApples + $PriceForOranges + $PriceForBananas;
    return $TotalPrice;
    }

Now, instead of printing out the result, the subroutine returns it. Now the part of the program that called it (above) will have the result plugged in where it was given.

Another very useful function can be used to get a yes or no answer from the user. This subroutine doesn't itself tell the user what he's supposed to answer yes or no about; that would be done just before calling this subroutine.

sub confirm()
    {
    $UserAnswer = <>;  # Read in the user's answer.
    chomp $UserAnswer;
    if ((not($UserAnswer eq "n")) and # If it's not a yes or a no,
      (not($UserAnswer eq "y")) and
      (not($UserAnswer eq "N")) and
      (not($UserAnswer eq "Y")))
	{
	while ((not($UserAnswer eq "n")) and # Keep going until we get a yes
	  (not($UserAnswer eq "y")) and      # or a no.
	  (not($UserAnswer eq "N")) and
	  (not($UserAnswer eq "Y")))
	    {
	    print "Please answer \"y\", for yes, or \"n\", for no.\n";
	    $UserAnswer = <>;
	    chomp $UserAnswer;
	    }
	}
    # If we've gotten here, the user has given a yes or a no answer.
    return (($UserAnswer eq "Y") or ($UserAnswer eq "y"));
    }

This procedure makes sure that the user types a y or n, then returns a conditional that says that the user said yes. So, for example, one could have the following segment of code:

print "Do you wish to continue (y/n)? ";
if (&confirm())
    {
    print "Continuing...\n";
    }
else
    {
    print "Bye!\n";
    exit 0;
    }

That segment of code asks the user if he wants to continue. If he says yes, then the program says "Continuing...", and continues. If he says no, the program says "Bye!", and exits.

That's all of the bare bones rudiments of programming. Now we can move onward to looking at a few sample programs, and then begin tinkering!

See also:

Statements - Variables - Flow control - Blocks - Subroutines and functions - Arguments - Subroutines

Sample programs

Here, we will look at a couple of sample programs, to get an idea of how they tick — how one might put the pieces together to make something. What I have done is a lot like showing you a number of Lego blocks all by themselves — here is a hint on how you might put them together.

We will look at two programs — one that keeps track of your friends and their pets, and another that keeps a running average of numbers it is given.

I would like for you to read over them, see the explanations, understand them — and then see what you can do with them. Can you modify them? Can you build something else from scratch? Try it!

See also:

Friends and pets - Running average

Friends and pets

Here, we will have a program that asks you about you friends and pets, and remembers them for as long as it's running. Let me give a listing. I am trying to document it well by putting in comments. Can you tell what it does? If you can't, look up the parts you can't understand.

#!/usr/bin/perl -w
#
# Friends and pets — a program to keep track of your friends and their pets.
#
# Last modified 12-29-01, by CJS Hayward
#
# While you say you want to continue, it asks you for another friend's name,
# and then asks for the pet's name.  Then, it tells you all of the friends it's
# been told, and what their pets are.
#
# This is done with a while loop.
# The friends are stored in a list, and
# the pets are stored in a hash.
#
# We also use a couple of functions.
#

#
# The stuff it does in the beginning, called initialization.
#

# List the subroutines and functions.
sub Confirm();

#
# Confirm is a function that gets a yes or no answer from the user.
#
# Note that this function uses another function — ReadLine.  It is
# possible, and indeed very useful, to have one subroutine or function use
# other subroutines or functions.
#

sub Confirm()
    {
    $UserAnswer = &ReadLine();
    if ((not($UserAnswer eq "n")) and # If it's not a yes or a no,
      (not($UserAnswer eq "y")) and
      (not($UserAnswer eq "N")) and
      (not($UserAnswer eq "Y")))
        {
        while ((not($UserAnswer eq "n")) and # Keep going until we get a yes
          (not($UserAnswer eq "y")) and      # or a no.
          (not($UserAnswer eq "N")) and
          (not($UserAnswer eq "Y")))
            {
            print "Please answer \"y\", for yes, or \"n\", for no.\n";
	    $UserAnswer = &ReadLine();
            }
        }
    # If we've gotten here, the user has given a yes or a no answer.
    return (($UserAnswer eq "Y") or ($UserAnswer eq "y"));
    }

# Make the list of friends and hash of pets empty, so that they don't contain
# anything.
@Friends = ();
%Pets = ();

# Have scalars that we can use for true and false conditional clauses.
$True = 1;
$False = 0;

# Welcome the user to the program.
print "Welcome to the friends and pets program.\n";

$ShouldContinue = $True;

#
# The main loop.  This is where the meat of the program is.
#

while ($ShouldContinue)
    {

    # Read in the friend's name.
    print "Please enter the name of your friend:\n";
    $NewFriend = &ReadLine();

    # Add the new friend to the list.
    @Friends = (@Friends, $NewFriend);

    # Read in the friend's pet.
    print "Please enter the kind of pet $NewFriend has:\n";
    $NewPet = &ReadLine();

    # Add the new friend's pet to the list of hashes.
    $Pets{$NewFriend} = $NewPet;

    # Print a blank line, so that the output doesn't look too crowded:
    print "\n";

    # Now, recite the friends and their pets.
    foreach $CurrentFriend (@Friends)
	{
	$CurrentPet = $Pets{$CurrentFriend};
	print $CurrentFriend ."'s pet is a $CurrentPet.\n";
	}

    # Finally, ask the user if he wants to continue.
    print "Do you want to continue (y/n)?\n";
    $ShouldContinue = &Confirm();

    # And we reach the end of the loop.
    }


# If we get here in the program, the user does not want to continue.
# So, we say "Bye!", and leave.

print "Bye!\n";
exit 0;

#
# The program will never get here by itself, because it is after the exit
# statement.  But we can still put procedures and functions here.  We will put
# two functions here:
#

#
# ReadLine is a function that reads a line in, and gets rid of the trailing
# newline.  This does input exactly as specified earlier.
#

sub ReadLine()
    {
    $UserInput = <>;
    chomp $userinput;
    return $userinput;
    }

A sample output for this program might be:

Welcome to the friends and pets program.
Please enter the name of your friend:
Fred
Please enter the kind of pet Fred has:
furball

Fred's pet is a furball.
Do you want to continue (y/n)?
y
Please enter the name of your friend:
David
Please enter the kind of pet David has:
dog

Fred's pet is a furball.
David's pet is a dog.
Do you want to continue (y/n)?
n
Bye!

See also:

Sample programs - Running average

Running average

This program reads numbers and tells their running average:

#!/usr/bin/perl -w
$total = 0;
$number_of_items = 0;
$result = 0;
while(1) # 1 is always true.
    {
    print "Next item: ";
    $input_line = <>;
    chomp $input_line;
    $total = $total + $input_line;
    ++$number_of_items;
    $result = $total / $number_of_items;
    print "The average so far is " + $result + ".\n";
    }

See also:

Sample programs - Friends and pets

Debugging

Do you have a little brother or sister? If you don't, pretend you do—a brother, Fred, who's just barely old enough to walk.

Imagine that your mother tells your brother to go to the bathroom. So your brother walks to the bathroom, stands there a while, and then asks why he was sent there. Or imagine that you have a potted plant in the house, and your parents come home and find that your brother dug out dirt from the tree and is playing in the dirt. They clean up the mess and explain, very plainly, that he is not to play in dirt. So your brother tries to find something better, and pulls all the leaves off the plant and plays in the leaves.

Computers are like that. They don't understand what you mean—only the literal sense of what you said. If you say almost exactly what you mean, the computer will almost do what you mean, and the 'almost' can be very annoying. In this chapter, I'll explain how to fix common bugs, and close with how science can help you debug.

Common Bugs

Many common bugs come from one of two sources:

  1. Accidentally typing the wrong thing.
  2. Logical errors.

Logical and mathematical errors are things like being off by one. Subsequent sections will tell you something about typing errors.

Syntax errors

If a programming book tells you to write something a certain way, you should do exactly what you're told. If you're told to write:

@a=(1,2);
foreach $b (@a)
    {
	print $b;
    }

and you write:

@a=(1,2);
foreach b (@a)
    {
	print $b;
    }

What will happen?

Something different, and not what you want.

One dollar sign is missing, so the computer will do something different, and not what you want.

Can't the computer just do what you mean?

No. Knowing what you mean shows human intelligence, and the computer can't do it.

What happens quite often is that you write something a little different than what you thought—something a person wouldn't notice—but the computer can't correct. If you're having trouble, read your code closely to see that you typed exactly what you thought you typed.

Misspelling

What happens if you type:

$pizzas = 12;
print "$pizzzas\n";

What you'd like to happen is that it prints out the number 12. However, I put an extra 'z' in, so it prints out 0. Why? The variable $pizzas may be 12, but $pizzzas is a different variable, and it is not twelve.

If you're having trouble, make sure that every variable and function is spelled exactly the same way every time it appears.

Forgotten semicolon

What happens if you type the following line of code:

print "Hello, world!\n"

What you'd like is for it to print "Hello, world!". However, the program will crash. It's waiting for a semicolon, and if it's not there it'll get confused. Make sure that every line, unless you've been told it doesn't need a semicolon, has a semicolon.

Single and Double Equals

What happens if you run the following code:

$a = 1;
$b = 2;
if ($a = $b)
	{
	print "They're equal!";
	}
else
	{
	print "They're not equal.";
	}

What would you like to happen? It compares 1 and 2 and says that they're not equal. However, if you run this, it says that they're equal. Why? ($a = $b) says to make a equal to b. What we wanted was ($a == $b), which would compare them.

Use '=' to assign a value and '==' to compare. It's easy to use the wrong one and introduce bugs to your program.

Scientific Debugging

How does the scientific method work?

In a nutshell, there's something a scientist doesn't understand, so he makes a guess, and then makes a way to show if the guess is wrong. After a lot of testing, a guess that hasn't been shown wrong may become part of science.

When you don't understand something, making guesses and then testing them ("If my program's miscalculating, then the variables before this part will have the right values, but the variables after will have wrong values. I know! I'll put print statements before and after to tell me the variables' values") can help you see why your program's not functioning.

If you have a science teacher who programs computers, it would be very helpful to approach him sometime when he's not busy and ask, "How can the scientific method help me debug computer programs?"

Conclusion

I hope this has helped you to begin to tinker and play, exploring what your computer can do when you speak one of its languages. When you're ready to learn more, read good programming books, continue asking questions, and by all means, keep tinkering!

Would you like another book that will tell you more? O'Reilly publishes excellent titles. Learning Perl is an excellent next step. When you've outgrown that, Programming Perl, affectionately named the camel book by Perl programmers, will take you far.

And if you enjoyed this, would you like to see some of what else I've written? You might find some of it interesting.

-Jonathan

Glossary

Argument
Assignment
Atgry
Block
Bug
Code
Comma
Comment
Concatenate
Conditional clause
Dollar sign
Equals sign
Feature
Flow control
Function
Hash
Input
Language
Left curly brace
Left parenthesis
List
Loop
Output
Percent sign
Pound sign
Right curly brace
Right parenthesis
Scalar
Semicolon
Statement
String
Subroutine
Underscore
Value
Variable

[Certain terms are defined in the text; those remaining are:]

Definition: Atgry

An atgry (the plural of atgry is atgrynge) looks like this:

@

Atgrynge are used before variables that are lists. They are also known as 'at signs'.

Definition: Bug

A bug is a mistake in a program that makes the program act differently than it was supposed to.

Bugs are one of the facts of life in computer programming; we all make mistakes, and figuring out and fixing bugs is an important part of creating programs.

The term 'bug' comes a story that, way back in the middle bronze age when computers were made with physical relays, a computer wasn't doing something properly, and (after investigation) the people discovered that there was an insect which had gotten into the computer and was making it malfunction: the computer had a bug in it. Since then, we use the word 'bug' to refer to malfunctions that are caused by human mistakes as well as funny things like insects crawling into a computer.

Even when it seems like you've done everything right, sometimes the computer still won't do what you want it to. One of the points of maturity for a programmer is not to blame other things, but to realize that it's probably a mistake you've made, and to see what you need to do to fix it.

Definition: Code

Code is a word we use to refer to the "stuff" a program is made out of, just as 'wood' is a word we use to refer to the "stuff" a board is made out of. Here is an example of code:

#!/usr/local/bin/perl
#
# Print out the phrase "Hello, world!"
#

print "Hello, world!\n";

In this case, this code is all of a program; code can also be some of a program.

Can you identify the different parts of this program?

Definition: Comma

A comma looks like this:

,

Definition: Concatenate

When you concatenate two strings, you stick them both together, one after the other. For example:

If you concatenate:

"Old MacDonald had a farm. "

and

"On that farm, there was a cat. "

the result is,

"Old MacDonald had a farm. On that farm, there was a cat."

In Perl, you can concatenate strings by placing a period ('.') in between them. The following code assigns $first_part the value "Old MacDonald had a farm.", $second_part the value "On that farm, there was a cat. " before assigning the concatenated value to $combined:

$first_part = "Old MacDonald had a farm. ";
$second_part = "On that farm, there was a cat. ";
$combined = $first_part . $second_part;

Definition: Dollar sign

A dollar sign looks like this:

$It is used before the names of some variables — specifically, scalars, and (in some cases) hashes.

Definition: Equals sign

An equals sign looks like this:

=It is used for assignment.

Definition: Feature

A feature is some capability of a program, something that it can do. For example, most word processors can have bold or italic text, and print things out. Some time spent working on programs is adding new features.

There is a running joke among computer people, that when there's a bug that a customer discovers, the technical support people say, "Oh, you've discovered our new feature!" — they pretend the bug is really a special feature.

Definition: Hash

A hash looks like this:

#

Hashes are used in Perl to begin comments, and are also known as pound signs.

Definition: Language

There are different languages that humans use to communicate with each other — English, French, German, Italian, and so on. There are also languages for humans to tell computers to do things. Perl is one of many such languages.

Different computer languages have different strengths and weaknesses. Each one has a slightly different function — just like the tools in a tool chest (hammer, pliers, screwdriver, etc.) have different functions.

There is a difference between computer and human languages, which is this: Human languages are difficult to learn, at least for adults. Even if you can communicate well in English, you will have to work hard to be able to communicate even badly in French or German (if you have not already had experience with them). But with computer languages, once you have really learned to program, learning a new language is fairly easy.

This is part of why I am using Perl as the language for this book, instead of using the language I know best (C). Perl is a good, easy language to begin with, and I hope both that you can learn Perl, and move on to other languages that will teach you other things that Perl doesn't teach you very well. I think, for example, that Java is a good second language. After Perl and Java, you should be able to use almost any language.

Definition: Left curly brace

A left curly brace looks like this:

{

Left and right curly braces are used to enclose blocks of code, as well as designate an element of a hash.

Definition: Left Parenthesis

A left parenthesis (the plural of parenthesis is parentheses) looks like this:

(

Left and right parentheses are used to clarify what you mean in certain arithmetic expressions, as well as telling where the members of a list and the arguments to a function begin and end.

Definition: Percent sign

A percent sign looks like this:

%

Percent signs, among other things, are used to refer to hashes.

Definition: Period

A period looks like this:

.

Periods are used, among other things, to concatenate two strings, as explained in the section of the text on scalars.

Definition: Right curly brace

A right curly brace looks like this:

}

Right and left curly braces are used to enclose blocks of code, as well as designate an element of a hash.

Definition: Right parenthesis

A right parenthesis (the plural of parenthesis is parentheses) looks like this:

)

Right and left parentheses are used to clarify what you mean in certain arithmetic expressions, as well as telling where the members of a list and the arguments to a function begin and end.

Definition: Semicolon

A semicolon looks like this:

;

Semicolons are used at the end of most statements.

Definition: String

A string is some amount of text. Examples of strings are:

"My left foot"

"436"

"A man without eyes,
saw plums in a tree.
He neither ate them nor left them;
now, how could this be?"

We enclose a string in quotation marks, to indicate where the string begins and ends. The quotation marks are not actually part of the string. (Strings can contain almost anything, including line breaks and even quotation marks — although you have to be careful with quotation marks so you don't confuse the computer.)

Definition: Underscore An underscore looks like this:_Note that it is lower than a hyphen: here is a hyphen, followed by an underscore: -_.

Underscores, as well as letters and numbers, may be used in the names of variables and functions.

Definition: Value

A value is a specific meaning that a variable may have at once. For example, the scalar $NumberOfCats could have the value 1, 2, or 5. A variable may only have one value at a time; when it is given a new value, the new value replaces the old value. Here are some examples of values that a scalar may have:

"five of spades"

1

-2.5

Tinkering With Perl is a free book that provides an introduction to programming in Perl, as well as a basic reference for things like foreach in Perl, if-then, and if-then-else, in addition to providing a glossary where you can find definitions for concatenate and other terms.

Tinkering With Perl may be one of the most popular offerings on this site, but it's not the only attraction. You can read a tongue-in-cheek Game Review: Meatspace, and spend a few minutes wishing your boss would read, The Administrator Who Cried, "Important!" (Not to mention that there are other things you can read here besides tech stuff, from Janra Ball: The Headache to The Spectacles.)