Previous Up Next

This HTML version of Think Perl 6 is provided for convenience, but it is not the best format of the book. You might prefer to read the PDF version.

Chapter 2  Variables, Expressions and Statements

One of the most powerful features of a programming language is the ability to manipulate variables. Broadly speaking, a variable is a name that refers to a value. It might be more accurate to say that a variable is a container that has a name and holds a value.

2.1  Assignment Statements

An assignment statement uses the equals sign = and gives a value to a variable, but, before you can assign a value to a variable, you first need to create the variable by declaring it (if it does not already exist):

> my $message;          # variable declaration, no value yet
> $message = 'And now for something completely different';
And now for something completely different
> my $number = 42;      # variable declaration and assignment
42
> $number = 17;         # new assignment
17
> my $phi = 1.618033988;
1.618033988
>

This example makes four assignment statements. The first assigns a string to a new variable named $message, the second assigns the integer 42 to $number, the third reassigns the integer 17 to $number, and the fourth assigns the (approximate) value of the golden ratio to $phi.

There are two important syntax features to understand here.

First, in Perl, variable names start with a so-called sigil, i.e., a special non-alphanumeric character such as $, @, %, &, and some others. This special character tells us and the Perl compiler (the program that reads the code of our program and transforms it into computer instructions) which kind of variable it is. For example, the $ character indicates that the variables above are all scalar variables, which means that they can contain only one value at any given time. We’ll see later other types of variables that may contain more than one value.

Second, notice that all three variables above are first introduced by the keyword my, which is a way of declaring a new variable. Whenever you create a new variable in Perl, you need to declare it, i.e., tell Perl that you’re going to use that new variable; this is most commonly done with the my keyword, which declares a lexical variable. We will explain later what a lexical variable is; let’s just say for the time being that it enables you to make your variable local to a limited part of your code. One of the good consequences of the requirement to declare variables before you use them is that, if you accidentally make a typo when writing a variable name, the compiler will usually be able to tell you that you are using a variable that has not been declared previously and thus help you find your error. This has other far-reaching implications which we will examine later.

When we wrote at the beginning of this section that a variable has to be declared before it is used (or just when it is used), it plainly means that the declaration has to be before (or at the point of) the variable’s first use in the text file containing the program. We will see later that programs don’t necessarily run from top to bottom in the order in which the lines or code appear in the program file; still, the variable declaration must be before its use in the text file containing the program.

If you neglect to declare a variable, you get a syntax error:

> $number = 5;
===SORRY!=== Error while compiling <unknown file>
Variable '$number' is not declared
at <unknown file>:1
------> <BOL><HERE>$number = 5;
>

Please remember that you may obtain slightly different error messages depending on the version of Rakudo you run. The above message was obtained in February 2016; with a newer version (October 2016), the same error is now displayed somewhat more cleanly as:

>
> $number = 5;
===SORRY!=== Error while compiling:
Variable '$number' is not declared
at line 2
------> <BOL><HERE>$number = 5;
>

A common way to represent variables on paper is to write the name with an arrow pointing to its value. This kind of figure is called a state diagram because it shows what state each of the variables is in (think of it as the variable’s state of mind). Figure ?? shows the result of the previous example.


Figure 2.1: State diagram.

2.2  Variable Names

Programmers generally choose names for their variables that are meaningful—they document what the variable is used for.

Variable names can be as long as you like. They can contain both letters and numbers, but user-defined variable names can’t begin with a number. Variable names are case-sensitive, i.e., $message is not the same variable as $Message or $MESSAGE. It is legal to use uppercase letters, but it is conventional to use only lower case for most variables names. Some people nonetheless like to use $TitleCase for their variables or even pure $UPPERCASE for some special variables.

Unlike most other programming languages, Perl 6 does not require the letters and digits used in variable names to be plain ASCII. You can use all kinds of Unicode letters, i.e., letters from almost any language in the world, so that, for example, $brücke, $payé or $niño are valid variable names, which can be useful for non-English programmers (provided that these Unicode characters are handled correctly by your text editor and your screen configuration). Similarly, instead of using $phi for the name of the golden ratio variable, we might have used the Greek small letter phi, φ (Unicode code point U+03C6), just as we could have used the Greek small letter pi, π, for the well-known circle circumference to diameter ratio:

> my $φ = (5 ** .5 + 1)/2;       # golden ratio
1.61803398874989
> say 'Variable $φ = ', $φ;
Variable $φ = 1.61803398874989
> my $π = 4 * atan 1; 
3.14159265358979
> # you could also use the pi or π built-in constant:
> say pi
3.14159265358979

The underscore character, _, can appear anywhere in a variable name. It is often used in names with multiple words, such as $your_name or $airspeed_of_unladen_swallow.

You may even use dashes to create so-called “kebab case”1 and name those variables $your-name or $airspeed-of-unladen-swallow, and this might make them slightly easier to read: a dash - is valid in variable names provided it is immediately followed by an alphabetical character and preceded by an alphanumerical character. For example, $double-click or $la-niña are legitimate variable names. Similarly, you can use an apostrophe ' (a.k.a. single quote) between letters, so $isn't or $o'brien's-age are valid identifiers.

If you give a variable an illegal name, you get a syntax error:

> my $76trombones = 'big parade'
===SORRY!=== Error while compiling <unknown file>
Cannot declare a numeric variable
at <unknown file>:1
------> my $76<HERE>trombones = "big parade";
>
> my $more§ = 100000;
===SORRY!=== Error while compiling <unknown file>
Bogus postfix
at <unknown file>:1
------> my $more<HERE>§ = 100000;
(...)

$76trombones is illegal because it begins with a number. $more§ is illegal because it contains an illegal character, §.

If you’ve ever used another programming language and stumbled across a terse message such as "SyntaxError: invalid syntax", you will notice that the Perl designers have made quite a bit of effort to provide detailed, useful, and meaningful error messages.

Many programming languages have keywords or reserved words that are part of the syntax, such as if, while, or for, and thus cannot be used for identifying variables because this would create ambiguity. There is no such problem in Perl: since variable names start with a sigil, the compiler is always able to tell the difference between a keyword and a variable. Names such as $if or $while are syntactically valid variable identifiers in Perl (whether such names make sense is a different matter).

2.3  Expressions and Statements

An expression is a combination of terms and operators. Terms may be variables or literals, i.e., constant values such as a number or a string. A value all by itself is considered an expression, and so is a variable, so the following are all legal expressions:

> 42
42
> my $n = 17;
17
> $n;
17
> $n + 25;
42
>

When you type an expression at the prompt, the interpreter evaluates it, which means that it finds the value of the expression. In this example, $n has the value 17 and $n + 25 has the value 42.

A statement is a unit of code that has an effect, like creating a variable or displaying a value, and usually needs to end with a semi-colon ; (but the semi-colon can sometimes be omitted as we will see later):

> my $n = 17;
17
> say $n;
17

The first line is an assignment statement that gives a value to $n. The second line is a print statement that displays the value of $n.

When you type a statement and then press Enter, the interpreter executes it, which means that it does whatever the statement says.

An assignment can be combined with expressions using arithmetic operators. For example, you might write:

> my $answer = 17 + 25;
42
> say $answer;
42

The + symbol is obviously the addition operator and, after the assignment statement, the $answer variable contains the result of the addition. The terms on each side of the operator (here 17 and 25) are sometimes called the operands of the operation (an addition in this case).

Note that the REPL actually displays the result of the assignment (the first line with “42”), so that the print statement was not really necessary in this example under the REPL; from now on, for the sake of brevity, we will generally omit the print statements in the examples where the REPL displays the result.

In some cases, you want to add something to a variable and assign the result to that same variable. This could be written:

> my $answer = 17;
17
> $answer = $answer + 25;
42

Here, $answer is first declared with a value of 17. The next statement assigns to $answer the current value of $answer (i.e., 17) + 25. This is such a common operation that Perl, like many other programming languages, has a shortcut for this:

> my $answer = 17;
17
> $answer += 25;
42

The += operator combines the arithmetic addition operator and the assignment operator to modify a value and apply the result to a variable in one go, so that $n += 2 means: take the current value of $n, add 2, and assign the result to $n. This syntax works with all other arithmetic operators. For example, -= similarly performs a subtraction and an assignment, *= a multiplication and an assignment, etc. It can even be used with operators other than arithmetic operators, such as the string concatenation operator that we will see later.

Adding 1 to a variable is a very common version of this, so that there is a shortcut to the shortcut, the increment operator, which increments its argument by one, and returns the incremented value:

> my $n = 17;
17
> ++$n;
18
> say $n;
18

This is called the prefix increment operator, because the ++ operator is placed before the variable to be incremented. There is also a postfix version, $n++, which first returns the current value and then increments the variable by one. It would not make a difference in the code snippet above, but the result can be very different in slightly more complex expressions.

There is also a decrement operator --, which decrements its argument by one and also exists in a prefix and a postfix form.

2.4  Script Mode

So far we have run Perl in interactive mode, which means that you interact directly with the interpreter (the REPL). Interactive mode is a good way to get started, but if you are working with more than a few lines of code, it can be clumsy and even tedious.

The alternative is to use a text editor and save code in a file called a script and then run the interpreter in script mode to execute the script. By convention, Perl 6 scripts have names that end with .pl, .p6 or .pl6.

Please make sure that you’re really using a text editor and not a word-processing program (such as MS Word, OpenOffice or LibreOffice Writer). There is a very large number of text editors available for free. On Linux, you might use vi (or vim), emacs, gEdit, or nano. On Windows, you may use notepad (very limited) or notepad++. There are also many cross-platform editors or integrated development environments (IDEs) providing a text editor functionality, including padre, eclipse, or atom. Many of these provide various syntax highlighting capabilities, which might help you use correct syntax (and find some syntax errors).

Once you’ve saved your code into a file (say, for example, my_script.pl6), you can run the program by issuing the following command at the operating system prompt (for example in a Linux console or in a cmd window under Windows):

perl6 my_script.pl6

Because Perl provides both modes, you can test bits of code in interactive mode before you put them in a script. But there are differences between interactive mode and script mode that can be confusing.

For example, if you are using the Perl 6 interpreter as a calculator, you might type:

> my $miles = 26.2;
26.2
> $miles * 1.61;
42.182

The first line assigns a value to $miles and displays that value. The second line is an expression, so the interpreter evaluates it and displays the result. It turns out that a marathon is about 42 kilometers.

But if you type the same code into a script and run it, you get no output at all. In script mode, an expression, all by itself, has no visible effect. Perl actually evaluates the expression, but it doesn’t display the value unless you tell it to:

my $miles = 26.2;
say $miles * 1.61;

This behavior can be confusing at first. Let’s examine why.

A script usually contains a sequence of statements. If there is more than one statement, the results appear one at a time as the print statements execute.

For example, consider the following script:

say 1;
my $x = 2;
say $x;

It produces the following output:

1
2

The assignment statement produces no output.

To check your understanding, type the following statements in the Perl interpreter and see what they do:

5;
my $x = 5;
$x + 1;

Now put the same statements in a script and run it. What is the output? Modify the script by transforming each expression into a print statement and then run it again.

2.5  One-Liner Mode

Perl also has a one-liner mode, which enables you to type directly a very short script at the operating system prompt. Under Windows, it might look like this:

C:\Users\Laurent>perl6 -e "my $value = 42; say 'The answer is ', $value;"
The answer is 42

The -e option tells the compiler that the script to be run is not saved in a file but instead typed at the prompt between quotation marks immediately after this option.

Under Unix and Linux, you would replace double quotation marks with apostrophes (or single quotes) and apostrophes with double quotation marks:

$  perl6 -e 'my $value = 42; say "The answer is $value";'
The answer is 42

The one-liner above may not seem to be very useful, but throwaway one-liners can be very practical to perform simple one-off operations, such as quickly modifying a file not properly formatted, without having to save a script in a separate file before running it.

We will not give any additional details about the one-liner mode here, but will give some more useful examples later in this book; for example, Subsection ??, Subsection ?? (solving the “rot-13” exercise), or Subsection ?? (solving the exercise on consecutive double letters).

2.6  Order of Operations

When an expression contains more than one operator, the order of evaluation depends on the order of operations or operator precedence. For mathematical operators, Perl follows mathematical convention. The acronym PEMDAS2 is a useful way to remember the rules:

  • Parentheses have the highest (or tightest) precedence and can be used to force an expression to evaluate in the order you want. Since expressions in parentheses are evaluated first, 2 * (3-1) is 4, and (1+1)**(5-2) is 8. You can also use parentheses to make an expression easier to read, as in ($minute * 100) / 60, even if it doesn’t change the result.
  • Exponentiation has the next highest precedence, so 1 + 2**3 is 9 (1 + 8), not 27, and 2 * 3**2 is 18, not 36.
  • Multiplication and Division have higher precedence than Addition and Subtraction. So 2*3-1 is 5, not 4, and 6+4/2 is 8, not 5.
  • Operators with the same precedence are usually evaluated from left to right (except exponentiation). So in the expression $degrees / 2 * pi, the division happens first and the result is multiplied by pi, which is not the expected result. (Note that pi is not a variable, but a predefined constant in Perl 6, and therefore does not require a sigil.) To divide by 2 π, you can use parentheses:
    my $result = $degrees / (2 * pi);  
    

    or write $degrees / 2 / pi or $degrees / 2 / π, which will divide $degrees by 2, and then divide the result of that operation by π (which is equivalent $degrees by 2 π.

I don’t work very hard to remember the precedence of operators. If I can’t tell by looking at the expression, I use parentheses to make it obvious. If I don’t know for sure which of two operators has the higher precedence, then the next person reading or maintaining my code may also not know.

2.7  String Operations

In general, you can’t perform mathematical operations on strings, unless the strings look so much like numbers that Perl can transform or coerce them into numbers and still make sense, so the following are illegal:

'2'-'1a'    'eggs'/'easy'    'third'*'a charm'

For example, this produces an error:

> '2'-'1a'
Cannot convert string to number: trailing characters after number 
in '1?a' (indicated by ?)
  in block <unit> at <unknown file>:1

But the following expressions are valid because these strings can be coerced to numbers without any ambiguity:

> '2'-'1'
1
> '3'/'4'
0.75

The ~ operator performs string concatenation, which means it joins the strings by linking them end-to-end. For example:

> my $first = 'throat'
throat
> my $second = 'warbler'
warbler
> $first ~ $second
throatwarbler

The x operator also works on strings; it performs repetition. For example:

> 'ab' x 3;
ababab
> 42 x 3
424242
> 3 x 42
333333333333333333333333333333333333333333

Notice that, although the x operator somewhat looks like the multiplication operator when we write it by hand, x is obviously not commutative, contrary to the * multiplication operator. The first operator is a string or is coerced to a string (i.e., transformed into a string: 42 is coerced to ’42’), and the second operator has to be a number or something that can be transformed into a number.

2.8  Comments

As programs get bigger and more complicated, they get more difficult to read. Formal languages are dense, and it is often difficult to look at a piece of code and figure out what it is doing, or why.

For this reason, it is a good idea to add notes to your programs to explain in natural language what the program is doing. These notes are called comments, and they start with the # symbol:

# compute the percentage of the hour that has elapsed
my $percentage = ($minute * 100) / 60;

In this case, the comment appears on a line by itself. You can also put comments at the end of a line:

$percentage = ($minute * 100) / 60;     # percentage of an hour

Everything from the # to the end of the line is ignored—it has no effect on the execution of the program.

Comments are most useful when they document nonobvious features of the code. It is reasonable to assume that the reader can figure out what the code does; it is more useful to explain why.

This comment is redundant with the code and useless:

my $value = 5;        # assign 5 to $value

This comment, by contrast, contains useful information that is not in the code:

my $velocity = 5;     # velocity in meters/second. 

Good variable names can reduce the need for comments, but long names can make complex expressions hard to read, so there is a tradeoff.

2.9  Debugging

Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors. It is useful to distinguish between them in order to track them down more quickly.

Syntax error
“Syntax” refers to the structure of a program and the rules about that structure. For example, parentheses have to come in matching pairs, so (1 + 2) is legal, but 8) is a syntax error. 3

If there is a syntax error anywhere in your program, Perl displays an error message and quits without even starting to run your program, and you will obviously not be able to run the program. During the first few weeks of your programming career, you might spend a lot of time tracking down syntax errors. As you gain experience, you will make fewer errors and find them faster.

Runtime error
The second type of error is a runtime error, so called because the error does not appear until after the program has started running. These errors are also called exceptions because they usually indicate that something exceptional (and bad) has happened.

Runtime errors are rare in the simple programs you will see in the first few chapters, so it might be a while before you encounter one. We have seen one example of such errors, though, at the beginning of Section ?? (p. ??), when we tried to subtract '2'-'1a'.

Semantic error
The third type of error is semantic, which means related to meaning. If there is a semantic error in your program, it will run without generating error messages, but it will not do the right thing. It will do something else. Specifically, it will do what you told it to do, but not what you intended it to do.

Identifying semantic errors can be tricky because it requires you to work backward by looking at the output of the program and trying to figure out what it is doing.

2.10  Glossary

Variable
Informally, a name that refers to a value. More accurately, a variable is a container that has a name and holds a value.
Assignment
A statement that assigns a value to a variable.
State diagram
A graphical representation of a set of variables and the values they refer to.
Keyword
A reserved word that is used to parse a program; in many languages, you cannot use keywords like if, for, and while as variable names. This problem usually does not occur in Perl because variable names begin with a sigil.
Operand
A value or term next to an operator that is used in its evaluation.
Term
A variable or a literal value.
Expression
A combination of operators and terms that represents a single result.
Evaluate
To simplify an expression by performing the operations in order to yield a single value.
Statement
A section of code that represents a command or action. So far, the statements we have seen are assignments and print statements. Statements usually end with a semi-colon.
Execute
To run a statement and do what it says.
interactive mode (or interpreter mode):
A way of using the Perl interpreter by typing code at the prompt.
Script mode
A way of using the Perl interpreter to read code from a script and run it.
one-liner mode:
A way of using the Perl interpreter to read code passed at the operating system prompt and run it.
Script
A program stored in a file.
Order of operations
Rules governing the order in which expressions involving multiple operators and operands are evaluated. It is also called operator precedence.
Concatenate
To join two string operands end-to-end.
Comment
Information in a program that is meant for other programmers (or anyone reading the source code) and has no effect on the execution of the program.
Syntax error
An error in a program that makes it impossible to parse (and therefore impossible to compile and to run).
Exception
An error that is detected while the program is running.
Semantics
The meaning of a program.
Semantic error
An error in a program that makes it do something other than what the programmer intended.

2.11  Exercises

Exercise 1  

Repeating our advice from the previous chapter, whenever you learn a new feature, you should try it out in interactive mode (under the REPL) and make errors on purpose to see what goes wrong.

  • We’ve seen that $n = 42 is legal. What about 42 = $n?
  • How about $x = $y = 1? (Hint: note that you will have to declare both variables, for example with a statement such as my $x; my $y; or possibly my ($x, $y);, before you can run the above.)
  • In some languages, statements don’t have to end with a semi-colon, ;. What happens in script mode if you omit a semi-colon at the end of a Perl statement?
  • What if you put a period at the end of a statement?
  • In math notation you can multiply x and y like this: x y. What happens if you try that in Perl?
Exercise 2  

Practice using the Perl interpreter as a calculator:

  1. The volume of a sphere with radius r is 4/3 π r3. What is the volume of a sphere with radius 5?
  2. Suppose the cover price of a book is $24.95, but bookstores get a 40% discount. Shipping costs $3 for the first copy and 75 cents for each additional copy. What is the total wholesale cost for 60 copies?
  3. If I leave my house at 6:52 a.m. and run 1 mile at an easy pace (8:15 per mile), then 3 miles at tempo (7:12 per mile) and 1 mile at easy pace again, what time is it when I complete my running exercise?

1
Because the words appear to be skewered like pieces of food prepared for a barbecue.
2
US students are sometimes taught to use the "Please Excuse My Dear Aunt Sally" mnemonics to remember the right order of the letters in the acronym.
3
We are using “syntax error” here as a quasi-synonym for “compile-time error”; they are not exactly the same thing (you may in theory have syntax errors that are not compile-time errors and the other way around), but they can be deemed to be the same for practical purposes here. In Perl 6, compile-time errors have the “===SORRY!===” string at the beginning of the error message.

Are you using one of our books in a class?

We'd like to know about it. Please consider filling out this short survey.


Think DSP

Think Java

Think Bayes

Think Python 2e

Think Stats 2e

Think Complexity


Previous Up Next