Chapter 1. Introduction

This chapter is the big picture view of the language; don’t worry if you don’t understand everything that’s going on just yet. Worry if you get to the end of the book and you still don’t! There’s much going on, so you’ll spiral around some topics, revisit others, and with some practice see how it all fits together—it really is all about the practice.

Why Perl 6?

For starters, you have Learning Perl 6. You might as well get your money’s worth by using the language!

But what makes this an attractive language? The Perl family has always been fond of DWIM—Do What I Mean. Things that you do frequently should be easy to do, and the hardest things should still be possible. The usefulness of any programming language is measured by the extent to which it solves your problems.

Perl 6 is a great text processing language—possibly even better than Perl 5. The regular expressions (Chapter 15) have many new and exciting features that make it even easier to match and extract bits of text. The builtin grammar (Chapter 17) features allow you to easily write complex rules to handle and react to text.

Gradual typing (Chapter 3) allows you to annotate variables with restrictions about what you can store there. For example, you can specify that a number must be a whole number, or a positive number, or between two other numbers. You don’t have to use it (that’s the gradual part). You’ll be able to annotate what a subroutine accepts and what it should return. That can quickly reveal bugs at data boundaries.

Builtin concurrency (Chapter 18) features allow you to decompose problems into parts that you run separately and perhaps simultaneously. The language handles most of that for you.

Lazy lists and infinite lists allow you to process sequences without excessive copying or even having the entire list at one time (Chapter 6). You can easily create your own infinite lazy lists.

I could keep going, but you’ll run into more amazing features as you work your way through this book.

There will be times that you won’t want to use Perl 6. No language is the right tool for every job. If you like something else better or can finish a task faster with a different tool, more power to you! I hope, though, that this book helps you do what you need to do quickly and efficiently in Perl 6.

First Steps with the REPL

The REPL is a Read-Evaluate-Print-Loop tool that provides an interactive prompt. The REPL evaluates the code you type, shows you the result, then prompts you again. It’s a quick way to try out small snippets. When you run perl6 without arguments it starts its REPL:

% perl6
To exit type 'exit' or '^D'
>

The > is the prompt that waits for you to type something. When you type Return the REPL does its work. Try it by adding two numbers:

% perl6
> 2 + 2
4

If there’s an error it lets you know about it and prompts you again:

% perl6
> 2 + Hamadryas
===SORRY!=== Error while compiling:
Undeclared name:
    Hamadryas used at line 1
>

You don’t know why this failed yet because you’re at the beginning of the book. That doesn’t really matter as long as you know the REPL catches the error and gives you a new prompt. If you need to correct a mistake you should be able to use the up arrow to go back to the previous line (or further) to edit and rerun something.

Before you move on, you should know a few other tricks that can help you learn the geography of the language.

Note

When I write about methods in this book I generally preface them with the method call dot so you know they’re methods, as in .is-prime. The dot is not part of the name.

A method is a label for predefined behavior of an object. Every object has a type, and the .^name method tells you that type:

% perl6
> 3.^name
Int

The literal 3 is an object of type Int, for integer. Once you know what type something is you can read its documentation to find out what you can do with it.

Behavior is defined in classes (Chapter 12), and these classes can be based on more general classes through inheritance. You can use the .^mro method to see the inheritance chain (although the documentation also tells you):

% perl6
> 3.^mro
((Int) (Cool) (Any) (Mu))

An object can do all the behavior of all the classes it inherits from. This shows that 3 is an Int, which is a Cool (Convenient Object-Oriented Loop), which is an Any (a base class for just about everything), which is, finally, a Mu (a thingy that is not a thingy—think on that for awhile!).

Use .^methods to see the list of methods for an object:

% perl6
> 3.^methods
(Int Num Rat FatRat abs Bridge chr sqrt base
polymod expmod is-prime floor ceiling round
...)

The type is also an object (a type object). It’s the abstract expression of the thingy without a concrete value. It has methods too:

% perl6
> Int.^methods
(Int Num Rat FatRat abs Bridge chr sqrt base
polymod expmod is-prime floor ceiling round
...)

You can’t call many of those methods on a type object, though. You get an error because there’s no value yet:

% perl6
> Int.sqrt
Invocant of method 'sqrt' must be an object instance of
type 'Int', not a type object of type 'Int'.

The methods .^name, .^mro, and .^methods come from the language’s metaprogramming underpinnings. That’s a bit advanced for this book given the number of pages I have, so you won’t read more about that here.

Reading the Documentation

Now that you know about the REPL and how to find the type of an object, you probably want to read about those in the documentation. The p6doc program can do that:

% p6doc Int
... lots of text

If you want to know about a method you can add it to the type:

% p6doc Int.polymod
      method polymod

Defined as:
    method polymod(Int:D: +@mods)

Usage:
    INTEGER.polymod(LIST)
...

Sometimes you don’t find the docs where you expect them. When that happens try one of the inherited classes:

% p6doc Int.sqrt
No documentation found for method 'sqrt'

% p6doc Cool.sqrt
  routine sqrt

Defined as:
    sub sqrt(Numeric(Cool) $x)
    method sqrt()

...

I find myself mostly reading the docs online at https://docs.perl6.org. Worse than that, I Google something like “perl6 Int” and follow the first result. That site also has a handy search feature to help you find things without using a full text search. You can run the same site locally. Look for those details at the bottom of each page.

Basic Syntax

You often need to read code from the inside out, as you would a math formula, so that’s how I approach it here: starting from the very tiny and building up from there. This is a survey of the things you need to know and will read about in upcoming chapters. Don’t worry if you are a bit overwhelmed at this point. You’ll get used to these things as you practice.

Terms

At the lowest level a program has terms. These are the building blocks that form everything else. Think of these as the nouns of the language. Here are some terms:

2
e
π
'Hello'
$x
now

These include literal data, such as 2 and 'Hello'; variables, such as $x; and defined symbols, such as π. now is a term that represents the current time as an Instant object.

A variable typically starts with a sigil—a special character that denotes something about that variable. The variable $x has the $ sigil. Don’t worry about those just yet, although you’ll see more later in this chapter.

Operators and Expressions

An expression is a combination of terms and operators that produce a new value. If the terms are the nouns, operators are the verbs that specify the action. They turn one or more terms into a new value. Operands are the values that an operator uses. A unary operator does something to a single operand:

- 137           # negate 137 to make -137
+ '137'         # convert the string '137' to a number
$x++            # add 1 to the current value in $x

That # and the text following it is a comment (which you’ll see more about in a moment). It’s some text that the program ignores and is a convenient way for you to leave notes about your code. I’ll often use comments to reinforce a point or show the output of an expression.

A binary operator works on two operands. Normally these operators show up between the operands (infixed):

2 + 2            # add two numbers
$object.method() # the . method call operator
$x = 137         # assign a value to a variable

A ternary operator, such as the conditional operator, ?? !!, has three operands:

$some_value ?? 'Yes' !! 'No'    # choose one of two values

If the first thingy evaluates to True, it selects the second thingy. Otherwise it selects the third thingy. You’ll see more of these in Chapter 3.

Before, after, and around

Operators come in several varieties, with names that describe their position and the number of operands they expect. You’ll see these terms throughout the book. A prefix operator comes before its operand and usually takes only one operand. The increment operator is an example. It adds one to the number in $x:

++$x

A postfix operator comes after its operand. There are increment forms of this type as well:

$x++

A circumfix operator surrounds its operand. Examples include the parentheses and the double quote marks:

( 1, 2, 3 )
"Hello"

A postcircumfix operator surrounds its operand but comes after something else. A single-element access to an Array or a Hash surrounds the index and comes after the variable name. The [] and <> are the operators that come after the name but surround the key:

@array[0]
%hash<key>

Those terms are in the documentation. There are other ways you can arrange operators that don’t have standard terms, so I’ve fashioned my own that I don’t expect to use that much.

A precircumfix operator surrounds an operand and comes before other operands. The reduction operator (Chapter 6) surrounds an operator that it places between each of the items that follow it. This adds all the numbers without having to specify a + between every pair:

[+] 1, 2, 3

A circumfix infix operator surrounds an infix operator. The hyperoperators <<>> surround an operator and distribute that infix operator along the two lists (Chapter 6):

(1, 2, 3) <<+>> (4, 5, 6)

There are other arrangements you might encounter in this book, but you can generally tell how they work by picking apart the name.

Operators are actually methods. Their names look a bit complicated because they start with the sort of operator they are and have the symbol in angle brackets:

infix:<+>(1, 2)     # 3

my @array = 1, 2, 3
postcircumfix:<[ ]>( @array, 1 )

You won’t need these forms, but you should know that the operators figure out what to do based on the arguments.

Precedence

You can chain operations one after the other. Try this in the REPL:

1 + 2 + 3 + 4

The expression is evaluated in order of operator precedence and associativity. Precedence decides which operators go first and associativity figures out the order among operators of the same precedence (or even two of the same operator).

An operator’s precedence is relatively looser or tighter than other operators. With a chain of terms the tighter operator goes first. Multiplication (*) happens before addition (+), just like in high school algebra:

2 + 3 * 4       # 14

If you don’t like the order you can change it with parentheses. Things inside parentheses are computed before things outside. Another way to say that is that parentheses have the highest precedence. Now the addition happens first:

(2 + 3) * 4     # 20

If you have two operators of the same precedence then associativity decides the order of evaluation. Operators can be either left associative or right associative. The exponentiation operator is right associative, so the operation on the right happens first:

2 ** 3 ** 4     # 2.4178516392293e+24

It’s the same order as if you put explicit parentheses around the right two numbers:

2 ** (3 ** 4)     # 2.4178516392293e+24

Use parentheses to make the left operation happen first:

(2 ** 3) ** 4     # 4096

Some operators can’t be combined and don’t have associativity. The range operator is one of the operators you can’t combine:

0 .. 5       # Range operator, nonassociative
0 .. 3 .. 5  # Illegal

Statements

A statement is a complete, standalone part of a program. An expression can be a statement but it can also be part of a statement. Here’s a statement using put to output a message. It adds a newline for you:

put 'Hello Perl 6!'

You separate statements with a semicolon. Here are two statements; they are on separate lines but you still need a semicolon between them:

put 'Hello Perl 6!';
put 'The time is ', now;

You don’t need the ; unless another statement follows, but I tend to put a semicolon at the end of every statement because I know I’ll forget to add it when I add more code:

put 'Hello Perl 6!';
put 'The time is ', now

Most whitespace is insignificant, which means you can use it how you like to format your program. These statements have a differently organized manner:

put
    'Hello Perl 6!'

; put 'The time is ',
now               ;

There are a few situations where whitespace matters, but you’ll read about that when you need to know about it.

Blocks

A block (Chapter 5) combines one or more statements into a single unit by surrounding them with a set of braces. Sometimes the block has a control keyword, such as loop, attached to it. This block continually evaluates its statements until you stop the program with Control-C. This is an infinite loop:

loop {
    state $count = 0;
    sleep 1;
    print $count++, "\r";
    }

Each statement is separated by a semicolon and the last statement has a semicolon for good measure.

You don’t see a ; after the closing brace for that loop, but it’s implicitly there. A } followed by nothing more than whitespace until the end of the line implies a ;. If you have more stuff on the same line, though, you need a ; after the }:

loop { ... }; put "Done";

The ... (yada yada) operator is the way you signal that there’s something there but you don’t care to say what it is at the moment. Use it when you intend to fill in the details later. I’ll use those to hide code to save space in examples. It compiles but gives you an error when you run it. You’ll see this used throughout the book to shorten examples to fit on the page.

A block creates a lexical scope. You can see what this scope is based on the position of the braces (hence, lexical). Things you define inside a scope only matter inside that scope and the deeper scopes it defines. This limits the effects of many things to exactly where you need them. The effects of variables and modules are limited to their lexical scope.

Comments

Comments are a way to leave ourselves notes that the program doesn’t care about. The compiler mostly ignores these things. You can make a comment with a # when the compiler is expecting a new token. The compiler skips everything from that # to the end of the line. Here’s a mostly useless comment:

put 'Hello Perl 6!'; # output a message

A better comment expounds on the purpose, not the effect, of the code. This type of little program is often used as a first exercise to check that everything is working. The comment can say that:

put 'Hello Perl 6!'; # show that the program ran

An alternative is an embedded comment. Put your message inside the parentheses in #`( ) somewhere in your statement (or even between statements):

put #`(Marketing asked for this) 'Hello Perl 6!';

This is a nice way to have multiline comments:

#`(
* show that the program ran
* need to add blockchain email AI feature
)
put  'Hello Perl 6!';

Since a closing parenthesis ends the comment, you can’t have one in your comment.

Both of those are fine for short comments. Sometimes you want to comment out several lines to prevent them from running. If you put the # at the beginning of a line you effectively remove that line from the program:

loop {
    state $count = 0;
#   sleep 1;
    print $count, "\r";
    }

You might add another comment to remind yourself why that line is still in the code. Often programmers do this as they are debugging so they remember what was there before they started:

loop {
    state $count = 0;
# Testing this for ticket 1234 (bug://1234)
# I think that the sleep slows the program down too much
#   sleep 1;
    print $count, "\r";
    }

Unspace

In most places Perl 6 doesn’t care about whitespace, but there are some parts of the Perl 6 syntax that don’t allow spaces. Space between the name of a subroutine and its opening parenthesis for an argument list changes the meaning:

my-sub 1, 2, 3;            # three arguments
my-sub( 1, 2, 3 );         # three arguments
my-sub ( 1, 2, 3 );        # one argument (a List)

In that last line there’s a space between my-sub and the (. That compiles and runs, but instead of three arguments the subroutine gets a single List argument (Chapter 6). You can unspace that space with a backslash. Any whitespace following the \ is basically invisible to the compiler:

my-sub\ (1, 2, 3 );

You might want to do this to format code into columns to make it easier to read:

my-sub\            ( 2, 4, 8 );
my-much-longer-name( 1, 3, 7 );

Objects and Classes

Perl 6 is a class-based object system. I’ll skip most of the theory of object-oriented programming (that could be a whole other book), but you should know that in these systems a class (Chapter 12) defines the abstract structure and behavior of an object. The object is a particular concrete version of that class.

Most of the data in Perl 6 are objects, and each object knows what class defines it. Classes define methods, which are the behaviors of the object. Classes can inherit from another class to include its behavior, but they can also include roles that add behavior without inheritance. When you see class names in the digital version of this book the name should link to the online documentation for that class (for example, the Int class).

You create objects by calling a constructor method, often called .new (Chapter 12). You pass arguments to the method in parentheses after the method name:

my $fraction = Rat.new( 5, 4 );

There’s also a colon syntax for method arguments which relieves you from the burden of typing the closing parenthesis as long as there’s nothing more in the statement:

my $fraction = Rat.new: 5, 4;

Type objects represent the abstract idea of a class but aren’t objects. Sometimes they are useful as placeholders when you know what sort of object you want but you don’t know its value yet:

my $fraction = Rat;

With gradual typing you can restrict variables to fit into a type. These are runtime checks, so you don’t know that it didn’t work until you try it:

my Int $n;

Since you haven’t assigned a value to $n yet, it’s an Int type object. When you want to assign a value it must match that type:

$n = 137;          # works because it's an integer
$n = 'Hamadryas';  # fails

Look through a class’s documentation to see what sorts of things its objects can do. In many of the exercises I’ll ask you to use a method that I haven’t shown you. This trains you to go to the docs, but also lets you learn things about seeing what’s out there. This saves some space in the book. Let’s try some of those now.

Variables

Perl 6 has named values. They can be immutable, which means you can’t change the values once you set them. They can also be mutable, which means you can change the values. The mutable ones are commonly called variables, but they are also known as containers. A container holds a value and you can replace that value with another. You’ll read more about that in the next chapter. Despite the possibility that you can’t change the value, I’ll still call all of these “variables.”

A named value has an identifier—a fancy word for “name.” Names can include letters, digits, the underscore, the hyphen, and the apostrophe ('). You must start your name with a letter or digit. These are valid identifiers:

butterfly_name
butterfly-name
butterfly'name

The underscore, hyphen, or apostrophe can separate words to make them easier to read. Sometimes the underscore pattern is called snake case since the word separators crawl along the ground. The hyphen pattern is called kebab case (or sometimes lisp case).

Some people might feel more at home capitalizing the first letter of each word instead. This is known as camel case since it imitates the humps on a camel’s back. In this example there’s one hump, which is the best number of humps for a camel:

butterflyName

There are some rules with - and '. You can’t have two - or ' characters in a row, and the character after either must be a letter (not a number). Also, you cannot start an identifier with these characters. None of these are valid:

butterfly--name
butterfly''name
'butterfly
butterfly-1

A variable name combines a sigil with an identifier. The sigil is a character that gives some context to the identifier. A scalar is a single thingy. A scalar variable holds a single value and has a $ sigil. The $ looks similar to S, for scalar:

$butterfly_name

As you encounter the different types you’ll encounter the other sigils. The @ is for positionals (Chapter 6), the % is for associatives (Chapter 9), and the & is for callables (Chapter 11).

The first time you use a variable you must declare it. You do this so the compiler knows you definitely want to use that name and to avoid problems with misspelling variables. The my keyword declares the variable to be private to the current scope:

my $number;

The next time you use $number in that same scope you don’t need to declare it. You probably want to assign it a value. The = is the assignment operator:

$number = 137;

You initialize a variable first time you assign a value to it. You can do this at the same time that you declare it:

my $number = 137;

Since Perl 6 already knows which variables you intend to use it knows when you misspell one:

$numbear = 137;

You get an error that’s often aware enough to guess what you meant:

Variable '$numbear' is not declared. Did you mean '$number'?

Simple Output

To see what’s in a variable you can use (or “call”) the put routine. This outputs the value to standard output and adds a newline to the end:

put $number;

If you use say it calls the .gist method for you. This often results in the same output, but some complicated objects may summarize or elide data to give you something easier to read. These two do the same thing:

say $number;
put $number.gist;

If you don’t want to add a newline you can use print:

print $number;

There are also method forms of each of these:

$number.put;
$number.say;
$number.print;

Lexical Scope

A variable is only visible in its lexical scope. If you define a variable inside braces you can’t use it outside the braces:

{
my $number = 137;
}

$number = 5; # a compilation error

This is caught when you try to compile the program:

Variable '$number' is not declared

A variable of the same name can exist in the outer scope and isn’t disturbed when the same name is reused in a deeper scope:

my $number = 5;
put $number;

{
my $number = 137;
put $number;
}

put $number;

These are two different variables that happen to use the same name. The compiler can tell them apart based on where you declared them. The inner scope declaration “hides” the outer scope one, so the result is:

5
137
5

Sometimes a named value doesn’t have a sigil. These sigilless variables don’t create containers, which means that you can’t change their values. This makes them handy for values you don’t want anyone to accidentally change. Prefix the identifier with a \:

my \magic-number = 42;
magic-number.put;

These statements actually create terms, but since you declare them like variables it’s slightly easier to be a little wrong than pedantically correct.

Predefined Variables

Perl 6 defines several variables for you. These are prefixed with a sigil and then an additional character called a twigil. The combination of characters tells you something about the variable. Don’t worry about all the sorts of twigils that exist. Know that they do exist and that you can read about them at https://docs.perl6.org/language/variables or with p6doc:

% p6doc variables

The ? twigil marks values that the compiler sets as it does its work. These are compile-time variables. If you want to know the file the compiler is working on you can look in $?FILE. The $ is the sigil and the ? is the twigil:

put $?FILE;

The * twigil marks dynamic variables. These are looked up through the caller’s scope, but that’s not the important part for this section. Your program automatically sets these values. Some of them are about the environment of the program:

% perl6
To exit type 'exit' or '^D'
> $*EXECUTABLE
"/Applications/Rakudo/bin/perl6".IO
> $*PROGRAM
"interactive".IO
> $*USER
hamadryas
> $*CWD
"/Users/hamadryas".IO

Others provide information about your version of Perl 6. This information might be useful if you need to report an issue:

> $*PERL
Perl 6 (6.c)
> $*VM
moar (2018.04)

There are other dynamic variables for the standard filehandles. Each program gets output, input, and error filehandles. The standard output (the default place where output goes) is in $*OUT and standard error is in $*ERR. These are IO::Handle objects and you can call .put on them to make output:

$*OUT.put: 'Hello Hamadryas!';
$*ERR.put: 'Hello Hamadryas!';

Making and Running a Program

It’s time you wrote a program. That’s just a plain-text file that contains your source code. You don’t need any special software to create these files. They must be plain text though; word processors insert extra stuff and the compiler won’t tolerate that.

The first line in the program is typically the shebang line. That’s a Unix thing that lets a text file pretend to be a program. When you “run” the text file the system sees that the first two characters are #!. It uses the rest of that line as the name of the program that will actually run the code. That’s the interpreter:

#!/Applications/Rakudo/bin/perl6

Your package (or custom installation) may have installed it somewhere else, in which case you’d use that path:

#!/usr/local/bin/perl6

Some people use env since that looks through your PATH to find the program:

#!/usr/bin/env perl6

Windows doesn’t know about shebangs, but it’s a good idea to include the shebang anyway since useful programs tend to escape into the world (life will find a way). For the rest of the book I’ll leave off the shebang line just to save space.

The rest of your file is your program. Here’s a common one that tests that you’ve probably done everything right. If you can run this program you’ve probably installed everything correctly:

put 'Hello World!';

Ensure your editor is set to encode your file as UTF-8. Save the file using any name that you like. perl6 doesn’t care about the name, although the docs suggest a .p6 or .pl6 extension.

Run your program from the command line:

% perl6 hello-world.p6

When you do this perl6 first compiles the program. It sees all of your program text and parses it. That’s the compile time part of the process. If it finds no problem it then runs what it has already compiled.

If you want to check your program without running it you can use the -c switch. This is a syntax check:

% perl6 -c hello-world.p6

Most errors at this point are syntax errors; you wrote a program that Perl 6 couldn’t parse.

Summary

You’ve seen the basic structure of a program and how you build up a program from smaller elements. You wrote some very small programs. You have some insights into the documentation; you’ll get more practice with that throughout your programming career. Now the trick is to make slightly larger programs.

Get Learning Perl 6 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.