📄 ch02.htm
字号:
Perl function that operates on associative arrays or their elements, such as keys(),
foreach(), and delete().</P>
<P>Hash references are extremely powerful. Using them, you can build up complex data
structures containing all the Perl data types or references to those types. In the
following example, you use the standard assignment/dereference syntax described previously
and one of the other dereferencing syntaxes:</P>
<PRE><FONT COLOR="#0066FF">@array = (1, 2, 3);
%Hash = (
`foo'=> `bar',
`aref' => \@array,
`internalhash' => {
`birds' => `duck',
`plants' => `tomato'
}
);
# print out the simple scalar element
print $Hash{`foo'}, "\n";
# print out the elements of @array
print join(` `,@{$Hash{`aref'}}),"\n";
# print out the elements of the %internalhash
foreach $key (keys( %{$Hash{`internalhash'}} )){
print "Key is $key, value is $Hash{`internalhash'}->{$key} \n";
}
# prints:
bar
1 2 3
Key is plants, value is tomato
Key is birds, value is duck
</FONT></PRE>
<P>Note how you dereference the value corresponding to the internal hash key of %Hash
by using the -> dereferencing operator. You can use -> because the value is
itself a reference to an anonymous hash. Because it's a reference, you can use it
as a regular scalar element of the array and still emulate a multidimensional hash.
<DL>
<DT></DT>
</DL>
<CENTER>
<H3>
<HR WIDTH="84%">
<BR>
<FONT COLOR="#000077">CAUTION:</FONT></H3>
</CENTER>
<BLOCKQUOTE>
<P>Remember, in spite of appearances, arrays are always one dimensional within Perl.
You're only emulating multidimensionality here by using references. See PERLDSC for
more details.<BR>
<HR>
</BLOCKQUOTE>
<P><B><TT>References to References</TT></B> References, like any other Perl data
type, can have references to themselves. You may, for instance, have several references
to various types or data structures that you want to group together under a single
reference. Here's an example:</P>
<PRE><FONT COLOR="#0066FF">$scalar = "a string"; # a regular scalar
$array = [1, 2, 3]; # anonymous array
$hash = {"foo" => "bar", "baz" => "blech"}; # anonymous hash
$scalarref = \$scalar; # ref to scalar
$refref = [\$scalarref, \$array, \$hash]; # anon array of refs to refs
# print out the contents of the ref to ref to scalar
print $${$refref->[0]},"\n";
# print out the elements of the ref to ref to array
print join(` `,@{${$refref->[1]}}),"\n";
# print out the elements of the ref to ref to hash
foreach $key (keys( %{${$refref->[2]}} )){
print "Key is $key, value is ${${$refref->[2]}}{$key} \n";
}
# prints:
a string
1 2 3
Key is foo, value is bar
Key is baz, value is blech
</FONT></PRE>
<P>You can go as deep as you like with references to references. Of course, at some
point, readability may suffer. I recommend readability over complexity in most cases,
especially in a public interface to a module or library, or within code that may
require modifications by someone other than yourself in the future. <B><TT>References
to Subroutines</TT></B> The last type of standard reference to look at, before getting
to blessed references and object-<BR>
oriented Perl, is the reference to code. Specifically, let's look at how to set up
and use a reference to a subroutine.</P>
<P>References to subroutines may be useful in a number of situations. You can use
them to implement closures, as previously described, or as subroutine parameters,
or as part of complex data types. Subroutine references are also useful within packages,
but note that you can't take an external (to a package) reference to a subroutine
which is within the external package, because of inheritance. See PERLSUB for more
details.</P>
<P>The following example illustrates a simple case in which you set up an array of
references to subroutines in the same package. Here, you use two types of references
to access the subroutines:</P>
<PRE><FONT COLOR="#0066FF">sub foo{
return "I\'m in foo now\n";
}
sub bar{
return "Here I am in bar\n";
}
%subrefs = (`foo' => \&foo, `bar' => `bar', ); # bar is a "fake" reference
while(($key,$ref) = each(%subrefs)){
print ${key}, " : ", &$ref;
}
# prints:
foo : I'm in foo now
baz : Here I am in baz
</FONT></PRE>
<P>You set up a single hash to contain multiple references to subroutines. The potential
for dynamic runtime decision trees should be evident. You could arbitrarily assign
references to subroutines at runtime, based on some input parameters, for instance,
then execute the subroutines using the references. You could have easily done the
same with a regular scalar array, emulating a C-style array of pointers to functions--not
as powerful as a hash of function pointers, but potentially useful.</P>
<P>Note how, in the preceding example when setting up the reference to the bar subroutine
in the %subrefs declaration, I didn't use the \ operator to prepend it. Instead,
you use a fake reference, which is another way to access a given data type by its
name. This technique could also be used in Perl4; however, it works for any data
type in Perl5, and it is an actual reference in Perl5. You can easily declare another
(fake) reference to fake reference, to any depth. The ref.t test suite has a nice
example for using fake references. I won't discuss them much more, because they're
not widely used, but they're worth noting. <B><TT>References to Packages (When Blessed)</TT></B>
When the reference variable refers to a Perl package and has been blessed into the
package, as shown in Table 2.2, it is known as a Perl object. It can then be used
to store, and allow access to, any Perl data type that is used by the package, akin
to public instance variables being accessed by a reference in C++.</P>
<P>You also can use the blessed reference to invoke the methods of the package, also
analogous to a C++ class reference. When you use a blessed reference in this way,
the method that gets invoked automatically has access to the object. This technique
is very common in the Perl modules, and it's very powerful. You need to have a clear
understanding of it in order to use and reuse the examples in this book and modify
them to suit your needs.</P>
<P>Let me give you a simple example to illustrate the concepts. In this example,
the object is a reference to hash. You could simplify it to a reference to array
or scalar, if it were appropriate. A hash reference gives the most flexibility to
access and grow the object dynamically. Consider the following:</P>
<PRE><FONT COLOR="#0066FF">package Customer;
sub new {
my $type = shift;
my %args = @_;
my $self = {};
$self->{`Name'} =
length($args{`Name'}) ? $args{`Name'} : "No name given";
$self->{`Vitals'} =
defined(@{$args{`Vitals'}}) ? $args{`Vitals'} : ["No vitals"];
bless $self, $type;
}
sub dumpcust{
my $self = shift;
# Print out the values for the object
print $self->{Name},"\n";
print join(` `,@{$self->{Vitals}}),"\n";
}
package main;
# Create a new customer object
$cust = Customer->new( `Name' => "Billy T. Kid",
`Vitals' => ["Age : 42", "Sex : M"] );
# Invoke the method to print out the values for the object
print $cust->dumpcust;
# prints:
Billy T. Kid
Age : 42 Sex : M
</FONT></PRE>
<P>In this simple example, you see how to initialize the Perl object, which is a
reference to hash, with both scalar elements and a reference to a scalar array. Then
you invoke the dumpcust() method from the Customer package or class, using the blessed
reference.</P>
<P>I'll continue to develop this example as we progress into the extended study of
the Perl module, and the object-oriented features of Perl programming.
<CENTER>
<H4><A NAME="Heading22"></A><FONT COLOR="#000077">An In-Depth Look at Perl5 Modules</FONT></H4>
</CENTER>
<P>You're now ready to take an extended look at Perl5 modules. In the following sections,
I'll give you a short history of the extensibility of Perl to demonstrate the usefulness
of modules. Then we'll look at the general style and process for implementing a module.
<CENTER>
<H4><A NAME="Heading23"></A><FONT COLOR="#000077">The Short History of Perl Extensions</FONT></H4>
</CENTER>
<P>In earlier versions of Perl, a number of external APIs, or extensions, were added
to Perl to give it additional features or functionality. This was accomplished by
compiling the Perl source code with source code that "glued in" the desired
functions from the API. Linking with the external libraries for the desired API then
created a new Perl executable. The following are a few examples:
<UL>
<LI>cursePerl: UNIX terminal control routines
<P>
<LI>tkPerl: Tk routines for screen graphics and widgets
<P>
<LI>sybPerl: Sybase database manipulation routines
</UL>
<P>Each of these executables had to be separately maintained by the person at the
site who compiled Perl, and each time one of the APIs was revised, that person had
to rebuild the complete API-specific Perl executable, relinking it with the new library
and working out any problems that might show up with the newer version. Perl5 has
outdated this tedious process. Nowadays, when you want to add features to Perl by
linking with some external library, you use a completely different techniques.
<CENTER>
<H4><A NAME="Heading24"></A><FONT COLOR="#000077">Modules and Extensions: Purpose
and Design</FONT></H4>
</CENTER>
<P>Version 5 of Perl implements the module as the standardized means for extending
its functionality. A Perl module is very much like a Perl library in that it provides
the user with a set of functions or variables, within a separate namespace known
as a Perl package. The purpose of these functions or variables is to simplify and
standardize the implementation of a given task or tasks.</P>
<P>Modules can be much more powerful and useful than the old-style Perl libraries,
however. First, they can now be implemented as a shared library and thus, on many
platforms, eliminate the need for a separate, statically linked Perl executable for
each external API that is desired as a Perl extension. Second, they can be implemented
to provide an interface for use in the new, object-oriented way. <B><TT>Extension
Modules: Modules That Interface to External APIs</TT></B> A Perl5 module provides
the implementor with the means, through the use of XSUBs, to compile C code that
"wraps" or "glues" the functionality of an API into a shared
library that can be loaded by Perl at runtime. After Perl loads the shared library,
through a use or require statement, the glue code enables the end user to call the
API's functions from within the Perl program, passing Perl data types in and out.
This capability is one of the most powerful and useful new features in Perl5.
<DL>
<DT></DT>
</DL>
<CENTER>
<H3>
<HR WIDTH="83%">
<BR>
<FONT COLOR="#000077">NOTE:</FONT></H3>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -