Language serves not only to express thought but to make possible thoughts which could not exist without it.
Perl 6 is a work in progress, so the syntax is rapidly changing. This chapter is likely to be outdated by the time you read it. Even so, it provides a good baseline. If you start here, you’ll only have to catch up on a few months of changes (starting with the design documents after Apocalypse 6), instead of several years worth.
Pretend for a moment that you don’t know anything about Perl. You heard the language has some neat features, so you thought you might check it out. You go to the store and pick up a copy of Programming Perl because you think this Larry Wall guy might know something about it. It’s the latest version, put out for the 6.0.1 release of Perl. It’s not a delta document describing the changes, it’s an introduction, and you dive in with the curiosity of a kid who got a telescope for his birthday. This chapter is a first glimpse down that telescope.
There’s plenty of time later to analyze each feature and decide which you like and which you don’t. For now, take a step back and get a feel for the system as a whole, for what it’ll be like to work in it.
The
most basic building blocks of a programming language are its nouns,
the blobs of data that get sucked in, pushed around, altered in
various ways, and spat out to some new location. The blobs of data
are values: strings, numbers, etc., or composites of the simpler
values. Variables are just named containers for those values. The
three kinds of variables in Perl 6 are scalars, arrays, and hashes.
Each has an identifying symbol (or sigil) as part of the name of the
variable: $
for scalars, @
for
arrays, and %
for hashes. The sigils provide a
valuable visual distinction by making it immediately obvious what
kinds of behavior a particular variable is likely to have. But,
fundamentally, there’s little difference between the
three. Each variable is essentially a container for a value, whether
that value is single or collective. (This statement is an
oversimplification, as you’ll soon see.)
Scalars are all-purpose containers. They can hold strings, integers, floating- point numbers, and references to all kinds of objects and built-in types. For example:
$string = "Zaphod's just this guy, you know?"; $int = 42; $float = 3.14159; $arrayref = [ "Zaphod", "Ford", "Trillian" ]; $hashref = { "Zaphod" => 362, "Ford" => 1574, "Trillian" => 28 }; $subref = sub { print $string }; $object = Android.new;
A filehandle is just an ordinary object in an ordinary scalar variable. For example:
$filehandle = open $filename;
Array variables hold
simple ordered collections of scalar values. Individual values are
retrieved from the array by numeric index. The
“0” index holds the first value.
The @
sigil is part of the name of the variable
and stays the same no matter how the variable is used:
@array = ( "Zaphod", "Ford", "Trillian" ); $second_element = @array[1]; # Ford
To get the length of an array—that is, the number of elements
in an array—use the .length
method. The
.last
method returns the index of the last element
in an array—that is, the highest index in an array.
$count_elements = @array.length; $last_index = @array.last;
Hashes are unordered
collections of scalar values, stored and retrieved by a key index.
The simplest way to build a hash is by passing it a list of anonymous
pair objects. These are formed with the pair constructor
=>
. For example:
%hash = ( "Zaphod" => 362, "Ford" => 1574, "Trillian" => 28 );
The key for each value may be a string or an object, though there are some restrictions on object keys. Hashes that use object keys must be declared as such, for the sake of efficiency.[5]
$age = %hash{"Zaphod"}; # string $age = %hash{$name}; # string variable $age = %hash{$person}; # object
In list context, a hash returns a list of key/value pair objects. The
.kv
method returns a flattened list of keys and
values from a hash. So the assignment of a hash directly to an array:
@pairs = %hash;
breaks down into a list roughly equivalent to:
(pair1, pair2, pair3, etc...)
While the assignment of the flattened key/value list:
@flat = %hash.kv;
is roughly equivalent to:
(key1, value1, key2, value2, etc...)
The .keys
method returns a flattened list of all
the keys in a hash. The .values
method returns a
flattened list of all the values:
@keys = %hash.keys; @values = %hash.values;
References are largely transparent in Perl 6. There is a distinction between references and ordinary variables, but it’s minimized as much as possible in actual use, with automatic referencing and dereferencing where appropriate. Creating a reference to an array or hash requires no special syntax. You simply assign it to a scalar variable:
$arrayref = @array; $hashref = %hash;
References are implicitly dereferenced in many contexts, so array indexes and hash keys access individual elements directly from hashrefs and arrayrefs, just like they do with hashes and arrays:
$arrayref[1] $hashref{"Zaphod"}
Methods are called on arrayrefs and hashrefs just like they are on arrays and hashes. The referent—the underlying data type or object—determines which methods can be used with a particular reference and whether it can support indexed access:
$arrayref.length $hashref.kv
References to subroutines can be executed simply by passing the reference an argument list. The list can be empty, but the parentheses are required:
$subref($arg);
Arrayrefs and
hashrefs have
special syntax (@{...}
and
%{...}
) for dereferencing them in structures that
normally wouldn’t.
The primary difference between variables with the
$
sigil and variables with
@
or %
sigils is that they each
impose a different context. The $
sigil imposes a
scalar context, @
imposes list context, and
%
imposes hashlist context.[6]
Any array or list evaluated in scalar context returns an arrayref. This means that assigning an array:
@array = ( "Zaphod", "Ford", "Trillian" ); $arrayref = @array;
a list:
$arrayref = ( "Zaphod", "Ford", "Trillian" );
or an explicit anonymous arrayref:
$arrayref = [ "Zaphod", "Ford", "Trillian" ];
to a scalar variable all produce exactly the same structure: a reference to an array with three elements.
A single element in parentheses is not a list. The comma is the list constructor. Parentheses only group.[7]
So when a one-element list is assigned in scalar context, it stays a simple scalar value:
$value = (20);
If you want to create an arrayref of one element in scalar context,
use square brackets ([...]
) to explicitly
construct an anonymous array reference:
$arrayref = [20];
Again, because a list in scalar context is an arrayref, a hash-like list assigned to a scalar variable is simply a reference to an ordered array of pairs:
$pair_list = ( "Zaphod" => 362, "Ford" => 1574, "Trillian" => 28 );
You have to use curly braces ({...}
) to explicitly
construct a hash reference in scalar context:
$hashref = { "Zaphod" => 362, "Ford" => 1574, "Trillian" => 28 };
Variables with the @
sigil impose flattening list context. This means that if you
assign one array to another array, the original array is
“flattened”—treated as if it
were a simple list of values—and every element from the
original array is copied to the new array. The result is that the two
array variables contain entirely different data structures, each with
identical values:
@copy = @original;
A single value in list context is a one-element list, so it produces a one-element array on assignment:
@array = (20); @array = 20; # same
The
anonymous arrayref
constructor [...]
imposes
flattening list context internally, but prevents flattening from
outside. In scalar context, a simple list and an arrayref construct
produce the same result. But in list context, a simple list is
treated as a flattened list, while an arrayref construct is treated
as a list of one element, an arrayref:
@array = ( "Zaphod", "Ford", "Trillian" ); @array = [ "Zaphod", "Ford", "Trillian" ];
The first example above produces an array with three elements, while the second produces an array with one element and that element is a reference to an array with three elements. This is useful for building up complex data structures where simple values alternate with array references:
@array = ( "Marvin", [ "Zaphod", "Ford", "Trillian" ], "Zarniwoop" );
Similarly, in flattening list context a list of array variables are flattened into a single array, while a list of scalar variables are treated as a simple list, even if the scalar variables are arrayrefs. So, the first example produces an array containing all the elements of the three arrays, while the second produces an array of three arrayrefs:
@array = ( @array1, @array2, @array3 ); # single flattened list @array = ( $arrayref1, $arrayref1, $arrayref3 ); # 3 element list
A lone pair of parentheses is a special token meaning “empty list.” It produces an array structure with no elements in both scalar and list context:
$arrayref = ( ); @array = ( );
Variables with %
sigils
impose hashlist context, which expects a list
of pair objects. This is typically simply a list of anonymous pairs
built with the pair constructor, =>
, as
follows:
%hash = ( "Zaphod" => 362, "Ford" => 1574, "Trillian" => 28 );
Equally, in hashlist context a list of simple values is treated as a list of pairs. Note that this substitution of two values for a pair object is only possible in hashlist context:
%hash = ( "Zaphod", 362, "Ford", 1574, "Trillian", 28 );
Curly braces {...}
are the anonymous hash
reference constructor, but they don’t impose
hashlist context. This is because curly braces alone assigned to a
scalar variable define an anonymous subroutine:
# a sub reference that does nothing $subref = { "Zaphod", 362, "Ford", 1574, "Trillian", 28 };
You can’t use commas in place of pair constructors
when assigning a hash reference to a scalar variable, because
it’s the =>
that marks the
structure as a hash. So, the hash reference constructor
isn’t really {...}
, but
{... => ...}
. If there’s ever
any ambiguity, you can also force the right context by specifying
hash
or sub
before the block:
$subref = sub { print "Lost luggage.\n"; } $hashref = hash { "Zaphod", 362, "Ford", 1574, "Trillian", 28 };
Properties allow additional information to be attached to variables and values. As Damian likes to explain it, they’re much like sticky notes. You can take a note, scribble some important information on it, and slap it onto the refrigerator, your monitor, or the dashboard of your car. When you’re done, you peel it off and throw it away.
Some properties are attached at compile time. These are known as
“traits.” Traits are still
properties, just a particular kind of property. Traits are fixed to
the variable when it is declared and cannot be changed later.
Compile-time traits are set with the is
keyword:
my $pi is constant = 3.14159;
The constant
trait specifies that the value of the
variable can’t be changed.
Other properties are attached at runtime. They may modify only
values, not variables. They can be added and removed at any time
during the execution of the code. Runtime properties are set with the
but
keyword:
$true_value = 0 but true;
The true
property specifies that the value will
always evaluate as true, no matter what it is. This particular
property means the Perl 6 system
call can be
checked with a simple conditional. It still returns the same numeric
values it always has (0 on success and a numeric error code on
failure), but it flags the value with a property as true when the
call succeeds and false when it fails.
Internally, properties and traits are stored in hash-like structures
with the property name as the key. Both constant
and true
define their own values when
they’re set. Some properties take arguments for
their value:
my @array is dim(2,5,42);
Properties have proven to be an incredibly useful and extensible syntax. You’ll see them again and again throughout this chapter. They aren’t restricted to variables and values, but appear on subroutines, methods, classes, grammars, rules, and in parameter lists.
The most important thing to understand about the Perl 6 type system is that it’s completely optional. If you choose to use it, you’ll gain some benefits in optimization and interfacing between languages. The type system isn’t fully defined, but the basic groundwork is in place.
Perl 6 makes a distinction between the type of a value and the type
of a variable. A value type specifies what kind of values a variable
can hold. Putting an Int
type on a scalar says
that the scalar holds an integer value:
my Int $scalar;
Putting an Int
type on an array says that the
array holds integer values:
my Int @array;
And putting an Int
type on a hash says that the
hash holds integer values:
my Int %hash;
The variable type specifies what kind of container the variable is.
This is basically like a tie in Perl 5. Variable types are defined as
traits of the variable, with the is
keyword. The
sigils define an implicit variable type, so a variable with no type
is just:
my $scalar is Scalar; my @array is Array; my %hash is Hash;
Hierarchical data structures can have a complex value type. A hash that holds integer arrays:
my Array of Int %hash;
has the value type Array of Int
. The type syntax
is flexible, so you could also write that as:
my %hash is Hash of Array of Int;
and get the same data structure. This improves readability, especially in multilevel data structures:
my Array of Hash of Array of Int %hash; my %hash is Hash of Array of Hash of Array of Int;
[5] Any
object used as a hash key must have a .id
method
that returns a unique value for each unique object to avoid hashing
collisions. This method is provided by default in the universal base
class, so you only have to worry about uniqueness when you define
your own .id
methods.
[6] These three are not the only contexts in Perl 6. A complete discussion of Perl 6 contexts appears in Section 4.2 later in this chapter.
[7] One thread on
p6l suggested parentheses as list constructors. This formulation has
an unexpected effect in structures that use parentheses for grouping:
$val = 10 / (2 + 3)
is the value
“2”, while $val = ( 10 / (2 + 3))
is an array reference with a single element
“2”.
Get Perl 6 Essentials 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.