By Allison Randal, Dan Sugalski, Leopold Tötsch
Price: $29.95 USD
£20.95 GBP
Cover | Table of Contents | Colophon
$ 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.)$ 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.)$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;
$filehandle = open $filename;
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:@crew = ( "Zaphod", "Ford", "Trillian" ); $second_member = @crew[1]; # Ford
=
operator is for ordinary
assignment.
It
creates a copy of the values on the righthand side and assigns them
to the variables or data structures on the lefthand side:$copy = $original; @copies = @originals;
$copy and $original both have
the same value, and @copies has a copy of every
element in @originals.:=
operator is for binding assignment.
Instead of copying the value from one variable or structure to the
other, it creates an alias. An alias is an additional entry in the
symbol table with a different name for the one container:$a := $b; # $a and $b are aliases @c := @d; # @c and @d are aliases
$a also changes
$b and vice versa, because
they're just two separate names for the same
container. Binding assignment requires the same number of elements on
both sides, so both of these would be an error:# ($a, $b) := ($c); # error # ($a, $b) := ($c, $d, $e); # error
::= operator is a variant of the binding
operator that binds at compile time.+),
subtraction
(if,
unless, and
given/when.if statement checks
a
condition and executes its associated block only if that condition is
true. The condition can be any expression that evaluates to a truth
value. Parentheses around the condition are optional:if $blue {
print "True Blue.";
}
if statement can also have an unlimited number
of elsif statements that check additional
conditions when the preceding conditions are false. The final
else statement executes if all preceding
if and elsif conditions are
false:if $blue {
print "True Blue.";
} elsif $green {
print "Green, green, green they say . . . ";
} else {
print "Colorless green ideas sleep furiously.";
}
unless statement
is
the logical opposite of if. Its block executes
only when the tested condition is false:unless $fire {
print "All's well.";
}
elsunless statement, though
else works with unless.given expression (the switch)
to a series of when statements (the
cases). When a case matches the switch, its
block is executed:given $bugblatter {
when Beast::Trall { close_eyes( ); }
when 'ravenous' { toss('steak'); }
when .feeding { sneak_past( ); }
when /grrr+/ { cover_ears( ); }
when 2 { run_between( ); }
when (3..10) { run_away( ); }
}method. These differences will be discussed in
Chapter 6.sub keyword, followed by the name of
the sub, followed by the block that defines the sub:sub alert {
print "We have normality.";
}
$result = sum($a, $b, 42, 57);
$result = sum(first => 12, second => 21);
& sigil before the subroutine name in a call
will not turn off signature checking. In fact, in most contexts
prefixing the subroutine name with & will
return a reference to the subroutine instead of calling the
subroutine.sub standardize ($text, $method) {
my $clean;
given $method {
when 'length' { $clean = wrap($text, 72); }
when 'lower' { $clean = lowercase($text); }
. . .
}
return $clean;
}
standardizesub keyword, followed by the name of
the sub, followed by the block that defines the sub:sub alert {
print "We have normality.";
}
$result = sum($a, $b, 42, 57);
$result = sum(first => 12, second => 21);
& sigil before the subroutine name in a call
will not turn off signature checking. In fact, in most contexts
prefixing the subroutine name with & will
return a reference to the subroutine instead of calling the
subroutine.sub standardize ($text, $method) {
my $clean;
given $method {
when 'length' { $clean = wrap($text, 72); }
when 'lower' { $clean = lowercase($text); }
. . .
}
return $clean;
}
standardize has two scalar
parameters, $text and $method,
so it is called with two arguments, each a scalar value. The
parameters are lexical variables within the body of the sub. They
never need to be explicitly declared as my, even
under use strict because they're
declared by the subroutine declaration.@_ array:sub sum {
my $sum;
for @_ -> $number {
$sum += $number;
}
return $sum;
}
@_ array. If you want a subroutine that takes no arguments (and
complains when arguments are passed), define it with an empty
parameter list ( ).sub whole (@names, %flags) {
. . .
}
whole(@array, %hash);
? before the parameter name:sub someopt ($required1, $required2, ?$optional1, ?$optional2) {
. . .
}sub matchparams ($first, $second) { . . . }
matchparams($one, $two); # $one is bound to $first
# $two is bound to $second
sub namedparams ($first, ?$second, ?$third is rw) { . . . }
namedparams(third => 'Trillian', first => $name);
namedparams :third('Trillian'), :first($name);
$first binds to @array[0] and
$second binds to @array[1]:sub flat ($first, $second) { . . . }
flat(*@array);
$first is bound to
%hash{'first'}, and $second is
bound to %hash{'second'}:sub flat_hash ($first, $second) { . . . }
%hash = (first => 1, second => 2);
flat_hash(*%hash);
. . . (or "yada, yada,
yada") operator. So, all the preceding examples that
look like pseudocode with { . . . } for their body
are actually valid subroutine declarations.sub stubbly (Str $name, Int ?$days) { . . . }
sub stubbly (Str $name, Int ?$days) {
print "$name hasn't shaved in $days day";
print "s" if $days > 1;
}
subname( ), and accessible elsewhere with a fully
qualified call using the Package::Name::subname( )
syntax.
module My::Module {
sub firstsub ($param) { . . . }
sub secondsub {
mysub('arg'); # call the subroutine
}
}
module Other::Module {
use My::Module;
sub thirdsub {
My::Module::firstsub('arg');
}
}
My::Module and
Other::Module. My::Module
declares a subroutine firstsub and calls it from
within secondsub. Other::Module
declares a subroutine thirdsub that calls
firstsub using its fully qualified name.myed subroutine makes an entry in the
current lexical scratchpad with a & sigil.
Lexically scoped subs are called just like a normal subroutine:if $dining {
my sub dine ($who, $where) {
. . .
}
dine($zaphod, "Milliways");
}
# dine($arthur, "Nutri-Matic"); # error
dine is
fine, but the second would be a compile-time error because
dine doesn't exist in the outer
scope.our keyword declares a lexically scoped alias
to a package scoped subroutine (it has an entry both in the symbol
table of the current package and in the current lexical scratchpad).
This is useful under certain levels of strictness.if $dining {
our sub pay ($when, $what) {
. . .
}
pay($tuesday, "hamburger");
}
$make_tea = sub ($tealeaves, ?$sugar, ?$milk) { . . . }
for and
given is just another way of defining anonymous
subroutines. The arrow doesn't require parentheses
around its parameter list. It can't declare named
subs, and can't declare a return type.$make_tea = -> $tealeaves, ?$sugar, ?$milk { . . . }
$make_tea = {
my $tea = boil 'tealeaves';
combine $tea, 'sugar', 'milk';
}
return
statement within an arrow sub or bare block sub to return from an
anonymous sub. Blocks and arrow subs are commonly used for ordinary
control flow, so return ignores them and only
returns from subroutines defined with sub keyword
or methods.multi keyword before sub.
They're useful if you want
a routine that can handle different
types of arguments in different ways, but still appear as a single
subroutine to the user. For example, you might define an
add multisub with different behavior for integers,
floats, and certain types of
numeric objects:multi sub add (Int $first, Int $second) { . . . }
multi sub add (Num $first, Num $second) { . . . }
multi sub add (Imaginary $first, Imaginary $second) { . . . }
multi sub add (MyNum $first, MyNum $second) { . . . }
add($apples, $oranges);
add based
on the types of the arguments passed to it. The parameters used for
dispatch selection are called invocants. If you
want to use a limited set of parameters as invocants, mark the
boundary between invocant parameters and the rest of the signature
with a semicolon:multi sub add (Int $first, Int $second: Int $third) { . . . }
add will dispatch based on the
types of the first two arguments passed in, and ignore the type of
the third.assuming method takes a list of named arguments
and returns a subroutine reference, with each of the named arguments
bound to the original subroutine's parameter list.
If you have a subroutine multiply that multiplies
two numbers, you might create a subref $six_times
that sets the value for the $multiplier parameter,
so you can reuse it several times:sub multiply ($multiplicand, $multiplier) {
return $multiplicand * $multiplier;
}
$six_times = &multiply.assuming(multiplier => 6);
$six_times(9); # 54
$six_times(7); # 42
. . .
&six_times := &multiply.assuming(multiplier => 6); six_times(7); # 42
.wrap
method is similar to the
.assuming method, but more powerful. It takes a
subroutine reference as an argument and returns an ID object. Inside
the subref wrapper, the call statement marks the
point where the original subroutine will be executed.$id = &subname.wrap ({
# preprocess arguments
# or execute additional code
call;
# postprocess return value
# or execute additional code
})
subname( . . . ); # call the wrapped subroutine
call, and alter the outer return value by
capturing the result from call and explicitly
returning a value in the wrapper.$id = &subname.wrap (sub (*@args) {
# preprocess arguments
$result = call('modified', 'arguments');
# postprocess return value
return $result;
})
.wrap
allows the .unwrap method to remove a specific
wrapper:&subname.unwrap($id);
temped version instead. The
temp automatically removes the wrapper at the end
of its scope.{
temp &subname.wrap ({ . . . })
subname( . . . );
}
is
rw
property:sub storage is rw { . . . }
storage( ) = 5;
my sub assignable is rw {
my $proxy is Proxy(
FETCH => { . . . },
STORE => { . . . },
. . .
);
return $proxy;
}
assignable. It creates a proxy variable tied to a
Proxy class that defines FETCH
and STORE tie methods on the fly.