This is the seventh set of slightly updated slides from a Perl programming course that I held some years ago.
I want to share it with everyone looking for intransitive Perl-knowledge.
A table of content for all presentations can be found at i-can.eu.
The source code for the examples and the presentations in ODP format are on https://github.com/kberov/PerlProgrammingCourse
2. Contents
1. What is a Subroutine
2. Defining Subroutines
3. Invoking Subroutines
4. Subroutine arguments
5. Retrieving data from calling subroutines
Operator caller
6. Return values. Operator wantarray
7. Scope and Declarations
3. What is a Subroutine
• Subroutine
• a user-defined function
• identifier for a code block
• letters, digits, and underscores
• can't start with a digit
• optional ampersand (&) in front
4. Defining a Subroutine
• sub NAME BLOCK
sub NAME (PROTO) BLOCK
sub NAME : ATTRS BLOCK
sub NAME (PROTO) : ATTRS BLOCK
• Without a BLOCK it's just a forward declaration
• Without a NAME, it's an anonymous function
declaration – return value: CODE ref
See: perlfaq7/What's a closure?
• May optionally have attribute lists
See: attributes, Attribute::Handlers
• A subroutine may be defined anywhere in your
program
5. Defining a Subroutine
• sub NAME (PROTO) BLOCK
• The function declaration must be visible at
compile time
• The prototype is in effect only when not using
the & character
• Method calls are not influenced by prototypes
either
• The intent is primarily to let you define
subroutines that work like built-in functions
• See:perlsub/Prototypes
6. Invoking Subroutines
• Example:sub.pl
sub hope;
sub syntax($) {
print "This is 'Subroutines' slide "
.($_[0]||1) ."n";
}
syntax $ARGV[0];
#syntax();#Not enough arguments for...
hope;
hope();
&hope;
nope();
#nope;#Bareword "nope" not allowed...
sub hope { print "I hope you like Perl!n"; }
sub nope { print "I am a dangerous Bareword.n" }
my $code_ref = sub { print 'I am a closure'.$/ };
print $code_ref,$/;#CODE(0x817094c)
$code_ref->() or &$code_ref;
7. Subroutine arguments
• @_
contains the parameters passed to the
subroutine
• if you call a function with two arguments, they
will be stored in $_[0] and $_[1]
• Avoid to use ($_[0] .. $_[n]) directly unless you
want to modify the arguments.
• The array @_ is a local array, but its elements
are aliases for the actual scalar parameters
8. Subroutine arguments
• Example: sub_args.pl
use strict; use warnings; $ = $/;
sub modify($) {
print "The alias holding "
.($_[0]++) ." will be modifyedn";
}
modify($ARGV[0]);
print $ARGV[0];
copy_arg($ARGV[0]);
print $ARGV[0];
sub copy_arg {
my ($copy) = @_;
print "The copy holding "
.($copy++) ." will NOT modify $ARGV[0]n";
}
9. Retrieving data from
calling subroutines
• caller EXPR
caller
Returns the context of the current subroutine call.
• In scalar context, returns the caller's package name if
there is a caller and the undefined value otherwise.
• In list context, returns
($package, $filename, $line) = caller;
• In list context with EXPR, returns more...
• The value of EXPR indicates how many call frames to
go back before the current one.
10. Retrieving data from
calling subroutines
• Example:caller.pl
use Data::Dumper;
sub dump_stacktrace {
print shift || 'Dumping stacktrace:';
my $call_frame = 1;
local $,=$/;
my %i;
while(($i{package}, $i{filename}, $i{line},
$i{subroutine}, $i{hasargs}, $i{wantarray},
$i{evaltext}, $i{is_require}, $i{hints},
$i{bitmask}, $i{hinthash})
= caller($call_frame++)){
print Data::Dumper->Dump(
[%i],['call '.($call_frame-1)]
);
}
}
11. Retrieving data from
calling subroutines (2)
• Example: caller2.pl
package Calling;
require 'caller.pl';
run(@ARGV);
sub run {
print '"run" called';
OtherPackage::second(shift);
}
sub OtherPackage::second {
print '"second" called';
my@a = ThirdPackage::third(@_);
}
sub ThirdPackage::third {
print '"third" called';
dump_stacktrace('This is the stack trace:');
}
12. Return values.
Operator wantarray
• Return values
• (list, scalar, or void) depending on the
context of the subroutine call
• If you specify no return value:
• returns an empty list in list context,
• the undefined value in scalar context,
• nothing in void context.
• If you return one or more lists:
• these will be flattened together
13. Return values.
Operator wantarray (2)
• Return values
• A return statement may be used to
specify a return value
• The last evaluated statement becomes
automatically the return value
• If the last statement is a foreach or a
while, the returned value is unspecified
• The empty sub returns the empty list
14. Return values.
Operator wantarray
• Return values: return.pl
#prints favorite pet or a list of all pets
my @pets = qw|Goldy Amelia Jako|;
print run($ARGV[0]);
sub run {
my $pref = shift||'';#favorite or list of pets
if($pref) { favorite() }
else { local $,=$/; print pets() }
}
sub favorite {
'favorite:'.$pets[1]
}
sub pets {
return ('all pets:', @pets)
}
15. Return values.
Operator wantarray
• wantarray
• Returns true if the context of the currently
executing subroutine or eval is looking for
a list value
• Returns false if the context is looking for a
scalar.
• Returns the undefined value if the context
is looking for no value (void context).
16. Return values.
Operator wantarray
• wantarray
# prints favorite pet or a list of all pets,
# or nothing depending on context
my @pets = qw|Goldy Amelia Jako|;
run();
sub run {
if(defined $ARGV[0]) {
if($ARGV[0]==1) { my $favorite = pets() }
elsif($ARGV[0]==2) { my @pets = pets() }
}
else { pets() }
}
sub pets {
local $,=$/ and print ('all pets:', @pets) if wantarray;
return if not defined wantarray;
print 'favorite:'.$pets[1] if not wantarray;
}
18. Scope
• What is scope?
• Lexical/static scope can be defined by
• the boundary of a file
• any block – {}
• a subroutine
• an eval
• using my
• Global/package/dynamic scope can be defined
by using sub, our and local declarations
respectively
19. Declarations
• my - declare and assign a local variable
(lexical scoping)
• our - declare and assign a package
variable (lexical scoping)
• local - create a temporary value for a
global variable (dynamic scoping)
20. Declarations
• my $var;
A my declares the listed variables to be local
(lexically) to the enclosing block, file, or eval.
• If more than one value is listed, the list must be
placed in parentheses.
• a virable declared via my is private
• See: perlfunc/my, perlsub/Private Variables via my()
my $dog; #declare $dog lexically local
my (@cats, %dogs); #declare list of variables local
my $fish = "bob"; #declare $fish lexical, and init it
my @things = ('fish','cat');
#declare @things lexical, and init it
21. Declarations
• my $var;
Example:
my $dog = 'Puffy';
{
my $dog = 'Betty';
print 'My dog is named ' . $dog;
}
print 'My dog is named ' . $dog;
my ($fish, $cat, $parrot) = qw|Goldy Amelia Jako|;
print $fish, $cat, $parrot;
#print $lizard;
#Global symbol "$lizard" requires explicit package
name...
22. Declarations
• our EXPR
• associates a simple name with a package
variable in the current package
• can be used within the current scope
without prefixing it with package name
• can be used outside the current package
by prefixing it with the package name
23. Declarations
• our – Example:
{
package GoodDogs;
print 'We are in package ' . __PACKAGE__;
our $dog = 'Puffy';
{
print 'Our dog is named ' . $dog;
my $dog = 'Betty';
print 'My dog is named ' . $dog;
}
print 'My dog is named ' . $dog;
}{#delete this line and experiment
package BadDogs;
print $/.'We are in package ' . __PACKAGE__;
#print 'Previous dog is named ' . $dog;
print 'Your dog is named ' . $GoodDogs::dog;
our $dog = 'Bobby';
print 'Our dog is named ' . $dog;
}
24. Declarations
• local EXPR
• modifies the listed variables to be local to the
enclosing block, file, or eval
• If more than one value is listed, the list must
be placed in parentheses
25. Declarations
• local EXPR (2)
WARNING:
• prefer my instead of local – it's faster and safer
• exceptions are:
• global punctuation variables
• global filehandles and formats
• direct manipulation of the Perl symbol table itself
• local is mostly used when the current value of a
variable must be visible to called subroutines
26. Declarations
• local – Example:
use English;
{
local $^O = 'Win32';
local $OUTPUT_RECORD_SEPARATOR = "n-----n";#$
local $OUTPUT_FIELD_SEPARATOR = ': ';#$,
print 'We run on', $OSNAME;
open my $fh, $PROGRAM_NAME or die $OS_ERROR;#$0 $!
local $INPUT_RECORD_SEPARATOR ; #$/ enable
localized slurp mode
my $content = <$fh>;
close $fh;
print $content;
#my $^O = 'Solaris';#Can't use global $^O in
"my"...
}
print 'We run on ', $OSNAME;