Learning How to Program in Perl

Dr. David J. Ritchie, Mr. Jim Skrine, Mr. Bruce Webber

Washington Junior High Computer Club

April 29, 1998

Summary

This is the fourth of several handouts for a short course in learning how to program in a computer language called "perl".

1.0 Introduction

This is the fourth of several handouts for a short course in learning how to program in a computer language called "perl".

This handout will cover more features of the language. Again, the treatment will be very schematic because it is assumed that you are trying out the features as you go along.

An important part of learning any language is to be able to write it in a way that others can understand (and, also, in a way that you can understand several weeks or months later). One of the best ways to be able to do this is to adopt a clear style in writing your program.

In Part 2, the handout describes a recommended style. I strongly encourage you to adopt this style in writing your programs.

2.0 Language Features

This part focuses on defining and using subroutines (sometimes called functions). Subroutines are pieces of code that you write once and use from several different places. Not only does this make for less work but also fixing a problem in a subroutine results in it being fixed for all the situations in which you call the subroutine.

2.1 Defining and Invoking a Subroutine

To define a subroutine, simply type the wordsub followed by the name of the subroutine. Follow this with a block containing the statements that you wish to be executed whenever this subroutin is called.

To invoke (e.g., call, or use) the subroutine, simply write its name followed by parentheses.

You should put the main code of your program (which will invoke your subroutine) at the beginning of the file and follow it with the subroutine definitions.

There is no rule that requires this--it is simply a matter of style. If you put a subroutinedefinition at the beginning of, or in the middle of, other statements of your program, it will simply be skipped when the statements are executed (but the subroutine will of course be defined when the program is compiled).

#

# Example 1

# Invoking the PrintHangman subroutine

PrintHangman();

#

# Definition of PrintHangman subroutine

sub PrintHangman {

print ("***********\n");

print ("* -- ! -- *\n");

print ("* o ! o *\n");

print ("* ! *\n");

print ("* ooo *\n");

print ("* \------/*\n");

print (" *** \n");

print (" * \n");

print ("***********\n");

print ("* ******* *\n");

print ("* ******* *\n");

print ("* ******* *\n");

print ("* ******* *\n");

print (" ******* \n");

print (" ******* \n");

print (" *** *** \n");

print (" *** *** \n");

print (" *** *** \n");

print (" *** *** \n");

print ("***** *****\n");

print ("***** *****\n");

}

2.2 Arguments

What if we wanted to print out only part of the Hangman given in the example? We could of course have five different subroutines. But we could also pass an argument that specified how much of the Hangman to print and a final message. In Perl, the arguments are provided as a list within parentheses at the invokation.

#

# Example 2

# Invoke the PrintHangman subroutine to print five lines

PrintHangman(5, "I am going to win!");

#

# Define the PrintHangman subroutine to print lines per arg.

sub PrintHangman {

$LTP = $_[0];

$MSG = $_[1];

print ("***********\n") if ($LTP >= 1);

print ("* -- ! -- *\n") if ($LTP >= 2);

print ("* o ! o *\n") if ($LTP >= 3);

print ("* ! *\n") if ($LTP >= 4);

print ("* ooo *\n") if ($LTP >= 5);

print ("* \------/*\n") if ($LTP >= 6);

print (" *** \n") if ($LTP >= 7);

print (" * \n") if ($LTP >= 8);

print ("***********\n") if ($LTP >= 9);

print ("* ******* *\n") if ($LTP >= 10);

print ("* ******* *\n") if ($LTP >= 11);

print ("* ******* *\n") if ($LTP >= 12);

print ("* ******* *\n") if ($LTP >= 13);

print (" ******* \n") if ($LTP >= 14);

print (" ******* \n") if ($LTP >= 15);

print (" *** *** \n") if ($LTP >= 16);

print (" *** *** \n") if ($LTP >= 17);

print (" *** *** \n") if ($LTP >= 18);

print (" *** *** \n") if ($LTP >= 19);

print ("***** *****\n") if ($LTP >= 20);

print ("***** *****\n") if ($LTP >= 21);

print ("$MSG\n");

}

2.3 Return Values

In addition to accepting arguments, a subroutine can also return a value. In fact, all perl subroutines always return a value. The value of the subroutine is the value of the return statement or the value of the last expression evaluated in the subroutine.

#

# Example 3

# Provide an argument to a subroutine, invoke it, get a value

$a = 1;

$b = my_name($a);

print ("The value is $b\n");

#

# Define the subroutine

sub my_name {

$choice = $_[0];

if ($choice == 1) {$name = "David"

} else {$name = "Fred" }

return $name;

}

In the invokation of the subroutine, the scalar variable $a is set to a value. Then, the subroutine is invoked with that variable. The value returned by the subroutine is stored in the variable $b.

In the definition of the subroutine, the value of the first arguement is assigned to the variable $choice. Then, depending on the value of this variable, the variable $name is assigned a value and given in the return statement as the value of the subroutine.

2.5 Private and Semi-private Variables

In the example above, we were careful not to use the same variables in the subroutine as those in the main program. The variables are one and the same. If we had used $a in the subroutine, it would have been the same $a that was used in the main program. Sometimes it is desirable that the variables are the same; sometimes it is a disaster.

We can insulate the variables in the subroutine from those in the main program by using the "my" statement and/or the "local" statement.

The "my" statement makes a variable totally private--it can't even been seen by the subroutines you invoke--let alone the ones that invoke you.

The "local" statement hides the variables from the subroutine that calls you but leaves them visible to you and the subroutines you invoke.

#

# Example 4

# Show the use of my and local

my ($a);

local ($b);

$a = 1;

$b = my_name($a);

print ("The value is $b\n");

#

# Define the subroutine

sub my_name {

my ($a);

$a = $_[0];

if ($a == 1) {

$name = "David"

} else {

$name = "Fred"

}

print ("The value of a is $a.\nThe value of b is $b.\n");

return $name;

}

3.0 Perl Style Guide

Every language, whether English, Spanish, or perl, comes to have a set of styles that are expected by the readers and followed by the successful authors (those that have works read and used).

Here are some style rules for perl that you should follow:

Space Rules:

  1. Do space over four spaces when indenting.
  2. Don't put any space before the semicolon.
  3. Don't put a space between name of the function and its opening parenthesis.
  4. Do put a space after each comma.
  5. Do put a space around an operator.
  6. Do put a space around a complex subscript (inside the brackets).
  7. Do put a space before the opening curly bracket of a multiline block.

Block Rules:

  1. One line blocks may be put on a single line
  2. Don't put a semicolon in a short one-line block
  3. Do line up the closing curly brace of a multi-line block with the keyword that began the thing.
  4. Place the opening curly bracket on the same line as the keyword; otherwise, line up with the keyword.

General Rules:

  1. Do put a blank line between sections of code that do different things.
  2. Do break long lines after an operator (but not after an "and" or an "or").
  3. Do line up corresponding items vertically.
  4. Do omit redundant punctuation as long as clarity doesn't suffer.

Things to Think About:

  1. Take advantage of perl's philosophy of providing several ways to express something. Chose the way that emphasizes the most important aspect of what you are trying to do by placing it first in the perl "sentence".
  2. Realize that there are some times when you are just doing a "quick and dirty, throw-away" program to try out an idea and other times when you are writing something that will be with you for a long time. Vary your style accordingly.
  3. Consider the person who will eventually have to figure out your code. Realize that that person may be you several weeks or months from now! Make it easy to read your code and understand your intent. Even if perl will let you omit the parentheses, consider using them to show your intent.
  4. Choose names of variables, arrays, and subroutines that mean something!
  5. Try to write fewer throw-aways and more long lasting code. When you get something that is truly reusable, clean it up, and give it back to the perl community as a way of saying "thanks" for providing perl and all its libraries in the first place.