230 likes | 275 Views
Packages. So far our programs have consisted of a single package called main We can explicitly define the package a program is in using a package declaration package name ; To use a package we must import it use name. Stack.pm. package Stack; our @theStack; sub push($) {
E N D
Packages • So far our programs have consisted of a single package called main • We can explicitly define the package a program is in using a package declaration package name; • To use a package we must import it use name References
Stack.pm package Stack; our @theStack; sub push($) { push @theStack,@_; } sub pop() { return pop @theStack; } sub empty() { return $#theStack == -1; } 1; # Has to be here References
Main.pm use Stack; for ( $i = 0; $i < 10; $i++ ) { Stack::push( $i ); } while ( !Stack::empty() ) { print Stack::pop(),"\n"; } References
Exporting • Having to use the Stack:: in main is a pain. • What we would like is to simply be able to use the functions defined in a package • Every package has its own name space • A package can export some of its names to a program that uses it References
Beginning and Endings • A package may contain the following subroutines • BEGIN • Initializes the package. • END • Executed after the main part of your program has terminated References
Stack.pm package Stack; our @theStack; BEGIN { use Exporter (); our (@ISA, @EXPORT); @ISA = qw(Exporter); @EXPORT = qw(&ppush &ppop &pempty); } sub ppush($)… sub ppop()… sub pempty()… 1; References
A Problem • Given a file of city and country names, like this: Chicago, USA Frankfurt, Germany Berlin, Germany Washington, USA Helsinki, Finland New York, USA • Produce an output like this: Finland: Helsinki. Germany: Berlin, Frankfurt. USA: Chicago, New York, Washington. References
A Solution • Create a hash • Keys Country Name • Value List of Cities • Problem • Hashes can only hold scalar values • Make a string • … References
References • A reference is a scalar value that refers to an entire array or an entire hash (or to just about anything else). • References in Perl are like names for arrays and hashes. They're Perl's private, internal names, so you can be sure they're unambiguous. • You can't have a hash whose values are arrays. But a single reference can refer to an entire array, and references are scalars, so you can have a hash of references to arrays. References
Creating References • There are two ways to create a reference • If you put a \ in front of a variable, you get a reference to that variable. $aref = \@array; $href = \%hash; • Once the reference is stored in a variable like $aref or $href, you can copy it or store it just the same as any other scalar value: $xy = $aref; $p[3] = $href; $z = $p[3]; References
Creating References • The second way to create references is to use anonymous arrays • [ ITEMS ] makes a new, anonymous array, and returns a reference to that array • { ITEMS } makes a new, anonymous hash. and returns a reference to that hash. • Consider • $aref = [ 1, "foo", undef, 13 ]; • $href = { APR => 4, AUG => 8 }; References
Using References • If $aref contains a reference to an array, then you can put {$aref} anywhere you would normally put the name of an array. @{$aref} @{$aref} ${$aref}[3] = 17 • Using a hash reference is exactly the same: %{$href} keys %{$href} ${$href}{'red'} = 17 References
Syntactic Sugar • Here is some additional syntax that makes this stuff easier to read/type ${$aref}[3]$aref->[3] ${$href}{red}$href->{red} • Warning @array = ( 1, 2, 3 ); $aref = \@array; $aref->[1]; # refers to the 2 in @array $aref[3]; refers to the fourth element of a totally different array. • It's easy to forget to leave out the ->, and if you do, you'll get bizarre results. References
Finally while (<>) { chomp; my ($city, $country) = split /, /; push @{$table{$country}}, $city; } foreach $country (sort keys %table) { print "$country: "; my @cities = @{$table{$country}}; print join ', ', sort @cities; print ".\n"; } References
Other Stuff • You can make references to anything, including scalars, functions, and other references. • You can omit the curly brackets whenever the thing inside them is an atomic scalar variable • @$aref is the same as @{$aref}, and $$aref[1] is the same as ${$aref}[1]. • To see if a variable contains a reference, use the `ref' function. • If you try to use a reference like a string, you get a string like ARRAY(0x80f5dec) References
Scalar References $aScalar = 17; print "aScalar=$aScalar\n"; $scalarRef = \$aScalar; print "scalarRef=$$scalarRef\n"; $$scalarRef = 18; print "aScalar=$aScalar\n"; References
Function References $coderef = sub { print "Hello World\n" }; &$coderef; # or $coderef->() sub newprint { my $x = shift; return sub { my $y = shift; print "$x, $y!\n"; }; } $h = newprint("Howdy"); $g = newprint("Greetings"); &$h("world"); # or $h->(“world”) &$g("earthlings"); # or $g->(“earthlings”) References
Arrow Summarized • To summarize the arrow operator… • If the right side is either a [...], {...}, or a (...) then the left side must be either a reference to an array, a hash, or a subroutine respectively. • There is another use… • We can put a subroutine name on the right. The left then identifies where the subroutine can be found References
There is a Twist • When using the -> to call a subroutine in a package, the actual call looks something like this • Stack->push(1); • Stack::push(“Stack”,1); • In other words the name of the package is passed in a parameter • Why would you want to do this? • A subroutine could use the parameter… References
Objects • What do we need to make an object • Maybe put another way how is a package similar to and not similar to an object? • Why can’t I use my Stack package as a class? References
Bless • This function tells the thingy referenced by REF that it is now an object in the CLASSNAME package. If CLASSNAME is omitted, the current package is used. • Because a bless is often the last thing in a constructor, it returns the reference for convenience. References
Stack.pm package Stack; BEGIN { use Exporter (); our (@ISA, @EXPORT); @ISA = qw(Exporter); @EXPORT = qw(&ppush &ppop &pempty); } sub new { $class = shift; return bless [],$class; } sub ppush { $this = shift; $value = shift; push @$this,$value; } sub ppop { $this = shift; return pop @$this; } sub pempty { $this = shift; return $#$this == -1; } 1; References
Main.pl use Stack; $aStack = Stack->new(); for ( $i = 0; $i < 10; $i++ ) { $aStack->ppush( $i ); } while ( !$aStack->pempty() ) { print $aStack->ppop(),"\n"; } References