Perl References, Objects and Modules
Dave Cross
Magnum Solutions Ltd
What We Will Cover
● References
● Modules
● Objects
References
References
● What is a reference?
● Creating references
● Using references
● Why use references?
What is a Reference
● A reference is a bit like a pointer in languages like C and Pascal (but better)
● A reference is a unique way to refer to a variable
● A reference can always fit into a scalar variable
● A reference looks like SCALAR(0x20026730)
Creating References
● Put \ in front of a variable name
$scalar_ref = \$scalar;
$array_ref = \@array;
$hash_ref = \%hash;
● Can now treat it just like any other scalar
$var = $scalar_ref;
$refs[0] = $array_ref;
$another_ref = $refs[0];
Creating References (cont)
● It's also possible to create references to anonymous variables (similar to allocating memory using malloc in C)
● Create a reference to an anonymous array using [ ... ]
$arr = [ 'an', 'anon', 'array' ];
● Create a reference to an anonymous hash using { ... }
$hash = { 1 => 'an', 2 => 'anon', 3 => 'hash' };
● Anonymous arrays and hashes have no name. You can only access them via the reference
Creating References (cont)
● Two ways to create a reference to an array
@arr = (1, 2, 3, 4);
$aref1 = \@arr;
$aref2 = [@arr];
print "$aref1\n$aref2";
● Output:
ARRAY(0x20026800) ARRAY(0x2002bc00)
● Second method creates a copy of the array
● The same is true of hashes
Using References
● Consider an array variable, @array
● It has two parts, a symbol (@) and a name (array)
● Use {$aref} in place of the name to get back an array that you have a reference to
@array = @{$aref}; # original array
@rev = reverse @{$aref};
$elem = ${$aref}[0]; # one element
${$aref}[0] = 'foo';
● The same is true of hashes
● Use {$href} in place of the name to get back a hash that you have a reference to
%hash = %{$href}; # original hash
@keys = keys %{$href};
$elem = ${$href}{key}; # one element
${$href}{key} = 'foo';
Using References (cont)
● Dereferencing syntax can look a bit confusing
print ${$aref}[3];
● Make it easier by using the arrow notation
print $aref->[3];
Using References (cont)
● It is common to store references in arrays or hashes
my %french = (one => 'un', two => 'deux', three => 'trois');
my %german = (one => 'ein', two => 'zwei', three => 'drei');
my %translate = (french => \%french, german => \%german);
● Or (using anonymous variables)
my %translate = ( french => { one => 'un', two => 'deux',
three => 'trois' }, german => { one => 'ein',
two => 'zwei',
three => 'drei' } );
Using References (cont)
● Using references within data structures
my $lang = 'german';
my $num = 'two';
print "The $lang for $num is ";
print ${$translate{$lang}}{$num};
● This is where the arrow notation has a real advantage
print $translate{$lang}->{$num};
Using References (cont)
● You can find out what a reference is referring to using "ref"
$aref = [ 1, 2, 3 ];
print ref $aref; # prints ARRAY
$href = { 1 => 'one', 2 => 'two' };
print ref $href; # prints HASH
● Another example
my @refs = (\$scalar, \@array, \%hash);
foreach (@refs) {
print This is a ', ref $_, "\n";
}
References Exercises
● Create an array and take a reference to it
● Using the reference, print the values in the array
● Now do the same with an anonymous array
● Create hashes to represent at least three people (containing the keys forename, surname and gender)
● Put references to these hashes in an array called @people
● For each element in @people, print out selected data from the hash
Exercise Solutions
● Create an array and take a reference to it
my @array = ('some', 'random', 'data');
my $ref = \@array;
● Using the reference, print the values in the array
foreach (@{$ref}) { print "$_\n";
}
● Now do the same with an anonymous array
my $ref = ['some', 'random', 'data'];
foreach (@{$ref}) { print "$_\n";
}
Exercise Solutions (cont)
● Create hashes to represent at least three people (containing the keys forename, surname and gender)
my %buffy = (forename => 'Buffy', surname => 'Summers', gender => 'female');
my %willow = (forename => 'Willow', surname => 'Rosenberg', gender => 'female');
my %xander = (forename => 'Xander', surname => 'Harris', gender => 'male');
● Put references to these hashes in an array called @people
my @people = (\%buffy, \%xander, \%willow);
● For each element in @people, print out selected data from the hash
foreach (@people) {
print "$_->{forename} $_->{surname} is $_->{gender}\n";
}
Why Use References
● What does this do?
@arr1 = (1, 2, 3);
@arr2 = (4, 5, 6);
check_size(@arr1, @arr2);
sub check_size {
my (@a1, @a2) = @_;
print @a1 == @a2 ? 'Yes' : 'No';
}
● This doesn't work. Why?
● Arrays are combined in @_
● All elements end up in @a1
● How do we fix it?
● Pass references to the arrays
Why Use References (cont)
● Another attempt
@arr1 = (1, 2, 3);
@arr2 = (4, 5, 6);
check_size(\@arr1, \@arr2);
sub check_size {
my ($a1, $a2) = @_;
print @$a1 == @$a2 ? 'Yes' : 'No';
}
● Passing references means there is no list assignment
● All arrays are distributed correctly
● Note: @$a1 is a shortcut for @{$a1}
Why Use References (cont)
● Another use - complex data structures
● Try to create a 2D array in Perl
● First attempt
@arr_2d = ((1, 2, 3), (4, 5, 6), (7, 8, 9));
● This doesn't work
● @arr_2d contains (1, 2, 3, 4, 5, 6, 7, 8, 9)
● Any element in an array can only contain a scalar value
● This is known a array flattening
Why Use References (cont)
● 2D Array using references
@arr_2d = ([1, 2, 3], [4, 5, 6], [7, 8, 9]);
● But how do you access individual elements?
● $arr_2d[1] is ref to array (4, 5, 6)
● $arr_2d[1]->[1] is element 5
● You can even omit intermediate arrows
$arr_2d[1][1]
Why Use References (cont)
● Another version (using anonymous arrays)
$arr_2d = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
● $arr_2d->[1] is ref to array (4, 5, 6)
● $arr_2d->[1]->[1] is element 5
● Simplify to $arr_2d->[1][1]
● First arrow cannot be omitted
● $arr_2d[1] is different to $arr_2d->[1]
Why Use References (cont)
● More complex data structures
● Suppose you have this data file
Summers,Buffy,Slayer Giles,Rupert,Watcher Rosenburg,Willow,Witch Summers,Dawn,Key
● What's a good data structure?
● Hash for each record
● Hashes ordered in an array
● Array of hash references
Why Use References (cont)
● Building an array of hash references
my @peoples;
my @cols = qw(s_name f_name job);
while (<FILE>) { chomp;
my %rec;
@rec{@cols} = split /,/;
push @records, \%rec;
}
● That @rec{@cols} is known as a hash slice and it is very useful
● Using an array of hash references
foreach (@records) {
print "$_->{f_name} $_->{s_name} ";
print "is a $_->{job}\n";
}
Why Use References (cont)
● Many more possibilities
◆ Hash of hash references
◆ Hash of array references
◆ Multiple levels (array of hash of hash of array...)
◆ Many examples in "perldoc perldsc" (the data structures cookbook)
● More information
◆ perldoc perlreftut
◆ perldoc perlref
◆ perldoc perllol
◆ perldoc perldsc
Finding, Installing and Using Modules
Finding, Installing and Using Modules
● Finding modules
● Installing modules (hard way and easy way)
● Using modules
◆ Functional modules vs Object Modules
● Object example (DBI)
● Useful modules
Finding Modules
● Perl comes with over 100 modules (see perldoc perlmodlib for current list)
● Perl has a repository of freely-available modules - the Comprehensive Perl Archive Network (CPAN)
◆ http://www.cpan.org/
◆ http://search.cpan.org/
● Search by module name, distribution name or author name
● Note: CPAN also contains newer versions of standard modules
Installing Modules (the hard way)
● Download distribution file
MyModule-X.XX.tar.gz
● Unzip file
gunzip MyModule-X.XX.tar.gz
● Untar file
tar xvf MyModule-X.XX.tar
● Change directory
cd MyModule-X.XX
● Create Makefile
perl Makefile.PL
● Build Module
make
● Test Build
make test
● Install Module
make install
Installing Modules (the hard way) (cont)
● Note: May need root permissions for make install
● You can have your own personal module library
perl Makefile.PL PREFIX=~/perl
● Need to adjust @INC
◆ use lib '/home/dave/perl/lib';
◆ export PERL5LIB=/home/dave/perl/lib
Installing Modules (the easy way)
● Note: May not work (or may need some configuration) through a firewall
● CPAN.pm is included with newer Perls
● Automatically carries out installation process
● Can also handle required modules
● Still need to be root
● Using CPAN.pm
perl -MCPAN -eshell
CPAN> install My::Module
● Or
perl -MCPAN -e"install 'My::Module'"
● See also CPANPLUS.pm (on CPAN)
Installing Modules (the easy way, for Windows)
● ActivePerl comes with the Perl Package Manager (PPM)
● This makes it easy to install modules
C:\> ppm
PPM interactive shell (2.0) - type 'help' for available commands PPM> install XML-Parser
● Type "help" for list of commands
● ActiveState is working on making all of CPAN available
Using Modules
● Having installed a module the documentation is available using the standard "perldoc" command
perldoc CGI
● Two basic types of module
● Function vs Object
● Functional modules export new subroutines and variables into your program
● Object modules usually don't
● Difference not clear cut (e.g. CGI.pm)
Using Functional Modules
● Import defaults
use My::Module;
● Import optional components
use My::Module qw(my_sub @my_arr);
● Import defined sets of components
use My:Module qw(:advanced);
● Use imported components
$data = my_sub(@my_arr);
● Exports are defined by module author and should be documented in module documentation
Using Functional Modules (example)
use POSIX 'strftime';
use CGI ':standard';
my $title = 'The Time';
print header,
start_html(-title=>$title), h1($title),
p('The time is ', strftime('%H:%M on %A %d %B, %Y', localtime));
end_html;
● "strftime" is imported from POSIX.pm
● "header", "start_html", "h1", "p", "end_html" (and many more) are imported from CGI.pm
Using Object Modules
● Use the module
use My::Object;
● Create an object
$obj = My::Object->new;
● Note: "new" is just a convention
● Interact using object's methods
$obj->set_name($name);
● Interface is defined by module author and should be documented in module documentation
Using Object Modules (example)
use IO::File;
my $in = IO::File->new('in.dat', 'r') or die $!;
my $out = IO::File->new('out.dat', 'w') or die $!;
while ($_ = $in->getline) {
$out->print($_) if /some pattern/;
}
● $in and $out are both objects of class IO::File
● Interact with objects thru object methods like "getline" and
"print"
Extended Object Example (DBI)
● Devised by Tim Bunce (author of oraperl)
● Standardised access to any database system
◆ a bit like ODBC
● Two modules involved
◆ DataBase Interface (DBI) provides uniform set of database access functions to programmer
◆ DataBase Driver (DBD) translates DBI calls into the vendors API calls
Connecting to a Database
● Connection creates a database handle
◆ all other communication is through this handle
my $dbh =
DBI->connect("dbi:Oracle:$server", $user, $pass)
|| die "Can't connect: $DBI::errstr";
● Connection string can vary for different DBD modules
● Database handle is an object
Selecting Data
● Prepare SQL statement
my $sth1 =
$dbh->prepare('select col1
from table1');
my $sth2 =
$dbh->prepare("select col1 from table1
where id_col = $id");
● Check return value (syntax errors)
● $sth1 and $sth2 are also objects (from a different class)
● Execute prepared statement
$sth->execute;
● Still need to check for errors
Selecting Data (cont)
● Fetch data
while (my @row = $sth->fetchrow_array){
print "@row\n";
}
● Fields are returned in the same order as they are defined in the query
● Other fetch methods are available:
◆ fetchrow_arrayref
◆ fetchrow_hashref (keys are column names)
◆ fetchall_arrayref
◆ fetch (alias for fetchrow_arrayref)
Inserting, Updating and Deleting
● Statements that don't return data can be executed using the same method
my $sql = "update table1 set col1 = '$val' where id_col = $id";
my $sth = $dbh->prepare($sql);
$sth->execute;
● But there's a shortcut
$rows = $dbh->do($sql);
Useful Standard Modules
● constant - Creates constant values
● File::Copy - Copy files
● Time::Local - Convert times to epoch
● POSIX - Interface to POSIX
● Text::Parsewords - Parse words from text
● CGI - CGI applications
● Getopt::Std - Process command line options
● Carp - Better warn and die
● Cwd - Current working directory
● Benchmark - Timing code
● File::Basename - Break up filenames
● Data::Dumper - Dump data to text
Useful CPAN Modules
● Template - Insert data in boilerplate text
● DBI - Database access
● libnet - Various network protocols (e.g. Net::FTP)
● DateTime - Date/Time manipulation
● libwww - HTTP client library
● Number::Format - Formatting numbers
● HTML::Parser - Parsing HTML
● XML::Parser - Parsing XML
● Text::CSV - Parse CSV data
● Regexp::Common - Common regular expressions
● MIME::Lite - Creating and sending MIME emails
● Memoize - Cache function return values
More Information on Modules
● perldoc perlmodlib
● perldoc perlmodinstall
● perldoc CPAN
● perldoc module