📄 ch02.htm
字号:
}
$closure = &newanon(`anonymous');
{ # new lexical scope
&$closure(`subroutine');
}
# prints: Hey, I'm in an anonymous subroutine.
</FONT></PRE>
<P>A lexical variable declared within a closure remains intact in future invocations
of the subroutine, even if invoked outside the lexical scope of the declaration.
See PERLSUB and PERLREF for detailed examples and descriptions of closures. <B><TT>Multiple
Simultaneous DBM Implementations</TT></B> The Perl programmer can now access a number
of DBM implementations simultaneously within a program. Perl is now shipped with
SDBM, and consideration is being given to including the Berkeley DB implementation
by default with Perl, but this has not been implemented yet. GDBM, NDBM, and ODBM
are also available, if you have them on your machine. Having simultaneous DBM implementations
makes it easy to convert from one DBM format to another within the same program.</P>
<P>You should note that the older dbmopen() function has been deprecated in favor
of the tie() function. See PERLFUNC for more details on implementing a tie()'d DBM
hash. <B><TT>Flags on </TT>#!<TT> Line</TT></B> Any regular Perl command-line options
(flags) appended after the</P>
<PRE><FONT COLOR="#0066FF">#!/usr/bin/perl
</FONT></PRE>
<P>line in a program are now correctly interpreted, even if the script isn't executed
directly. The startup line:</P>
<PRE><FONT COLOR="#0066FF">#!/usr/bin/perl -d
</FONT></PRE>
<P>will, for instance, invoke the debugger each time the script is run.
<CENTER>
<H4><A NAME="Heading18"></A><FONT COLOR="#000077">Summary of the New Perl5 Features</FONT></H4>
</CENTER>
<P>Perl5 is easier to learn and use and is clearly more powerful than previous major
versions of Perl. Other new features, modules, and documentation that enhance Perl's
usability are also available but haven't been mentioned here. You should explore
them all as time allows.
<CENTER>
<H3><A NAME="Heading19"></A><FONT COLOR="#000077">Extended Perl5 Tutorial</FONT></H3>
</CENTER>
<P>Now that you've been introduced to the new features in Perl5, you're ready to
embark on an extended tutorial on references and modules. You need to understand
how these elements work so that you can make use of the examples to follow in this
book. There's a lot to cover here, so grab a cup of coffee, and I'll try to avoid
monotony. You might find it helpful to be sitting at your computer with your copy
of Perl5 ready to run so that you can try out the sample code as you go along.
<CENTER>
<H4><A NAME="Heading20"></A><FONT COLOR="#000077">References</FONT></H4>
</CENTER>
<P>In the past, the Perl programmer had to go through some contortions to implement
various complex data types, such as arrays of arrays. The notion of a variable that
"pointed" to another data type did not exist. With the advent of Perl5,
you now have the reference variable type. References are actually just standard Perl
scalar variables, which are assigned or initialized to allow them to be used to refer
or "point" to some other Perl data type. References give you powerful new
capabilities when writing Perl programs.</P>
<P>To create a new real reference variable, you use the following general syntax:</P>
<PRE><FONT COLOR="#0066FF">$variable = \datatype;
</FONT></PRE>
<P>Here, you set $variable to be a reference to datatype by preceding datatype with
a backslash. $variable can now be used to refer or assign to datatype using an explicit
form of a dereference, depending on what datatype is. Table 2.2 illustrates the syntax
for using real references. A number of other types of references also exist, each
with its own assignment syntax, but I won't explain those types just yet. <TT>Table
2.2. References: Data types and assignment/dereference syntax.<BR>
<BR>
</TT>
<TABLE BORDER="0">
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Data Type</TD>
<TD WIDTH="121" ALIGN="LEFT">Assignment Syntax</TD>
<TD ALIGN="LEFT">Dereference Syntax</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Scalar</TD>
<TD WIDTH="121" ALIGN="LEFT">$ref = \$var;</TD>
<TD ALIGN="LEFT">$$ref</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Scalar Array</TD>
<TD WIDTH="121" ALIGN="LEFT">$ref = \@array</TD>
<TD ALIGN="LEFT">@{$ref} or ${$ref}[0] for individual elements</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Hash</TD>
<TD WIDTH="121" ALIGN="LEFT">$ref = \%array</TD>
<TD ALIGN="LEFT">%{$ref} or ${$ref}{key} for</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">individual elements</TD>
<TD WIDTH="121" ALIGN="LEFT"></TD>
<TD ALIGN="LEFT"></TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Reference</TD>
<TD WIDTH="121" ALIGN="LEFT">$refref = \$ref</TD>
<TD ALIGN="LEFT">$$$ref</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Subroutine (CODE)</TD>
<TD WIDTH="121" ALIGN="LEFT">$ref = \&sub</TD>
<TD ALIGN="LEFT">&$sub</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="111" ALIGN="LEFT">Package</TD>
<TD WIDTH="121" ALIGN="LEFT">bless $ref, Package</TD>
<TD ALIGN="LEFT">$ref->method() $ref->variable</TD>
</TR>
</TABLE>
<BR>
<BR>
In the following sections, you'll look at each of these data types in depth, and
I'll demonstrate their use with some examples. These examples should provide you
with some general insight as to how each type of reference can be used, but note
that they are not comprehensive. You can study the full power and capabilities of
references by reading PERLREF and PERLDSC. Another potentially useful document for
studying how references work is the test script for references in the Perl distribution,
called ref.t. Under UNIX, you can find it in the t/op directory under the Perl build
directory. Under Macintosh, the t/op directory should be located within the installation
directory. Under Windows 95, this directory is named ntt, and the file has been given
the .ntt extension. Look for ntt/op/ref.ntt instead of t/op/ref.t under Windows(ntperl).
It contains a complete test suite for all types of Perl references. <B><TT>References
to Scalars</TT></B> Scalar variables, the simplest type of Perl variable, can be
referenced, as can all other types. Although the usefulness of references to simple
scalars may not be immediately evident, referencing is certainly an option.</P>
<P>Consider the following example:</P>
<PRE><FONT COLOR="#0066FF">$foo = "Initial value";
&update_scalar();
print $foo,"\n";
sub update_scalar{
$foo = "Updated";
}
# prints: Updated
</FONT></PRE>
<P>This example takes a global variable, $foo, and sets it to an initial value; then
it calls the update_scalar subroutine to set it to a new value. Simple enough, but
if the update_scalar subroutine lives in a package, you're out of luck. Observe the
following:</P>
<PRE><FONT COLOR="#0066FF">$foo = "Initial value";
&test::update_scalar();
print $foo,"\n";
package test;
sub update_scalar{
$foo = "Updated";
}
# prints: Initial value
</FONT></PRE>
<P>Here, the $foo variable doesn't get changed because the test package has its own
namespace and its own $foo variable, and can't access the $foo in main without some
specific semantics. When you work with modules and packages, you'll be faced with
this restriction.</P>
<P>So, what to do? Well, you could pass in the $foo from main as a parameter to the
subroutine and try to update it within the subroutine like this:</P>
<PRE><FONT COLOR="#0066FF">$foo = "Initial value";
&test::update_scalar($foo);
print $foo,"\n";
package test;
sub update_scalar{
($foo) = @_;
$foo = "Updated";
}
# prints: Initial value
</FONT></PRE>
<P>Alas, the $foo that gets updated in the update_scalar subroutine is just a copy
of the $foo that is passed in. You're still dealing with two specific variables,
in different packages, and you're essentially passing by value when you make a reassignment
within the subroutine. The experienced Perl4 programmer will recognize that there's
also the option of modifying $_[0] directly, but references provide a cleaner solution.</P>
<P>The solution I've chosen, using a reference to a scalar, is to create a reference
to main's $foo, pass it into the update_scalar subroutine, and then dereference for
the assignment, as follows:</P>
<PRE><FONT COLOR="#0066FF">$foo = "Initial value";
&test::update_scalar(\$foo);
print $foo,"\n";
package test;
sub update_scalar{
($foo) = @_;
$$foo = "Updated";
}
# prints: Updated
</FONT></PRE>
<P>Notice how you implicitly pass the reference to the subroutine by using the backslash
operator on main's $foo variable in the subroutine call. You thus pass main's $foo
by reference to the update_scalar subroutine, and when you assign it to the $foo
in the subroutine, you are actually creating a real reference to the $foo in main.
Using the dereferencing syntax described in Table 2.2, you then can change $main::foo
implicitly through the reference, using the $$foo dereferencing syntax.</P>
<P>References to scalar types have many uses; this simple example describes only
one. You'll see others as you continue to read through the chapters of this book.
<B><TT>References to Scalar Arrays</TT></B> Scalar arrays are arrays of Perl scalar
types. You declare them using the @name syntax. Using a reference to the scalar array
enables you to access the elements of an array individually or refer to the entire
array, as shown in Table 2.2. Of course, you also can use the reference anywhere
an array is expected, such as within a foreach() loop. The following example again
illustrates the usefulness of references when passing arguments to subroutines. Consider
the following code:</P>
<PRE><FONT COLOR="#0066FF">@array1 = (1, 3, 5);
@array2 = (2, 4, 6);
</FONT></PRE>
<P>Now, what if you want to pass these arrays to a Perl subroutine and then access
them within the subroutine, possibly modifying their values? If you've ever tried
to pass two or more arrays to a Perl subroutine, then you know that it can't be done
easily, because there's no way to determine where the first array ends and the next
one begins. (Recall that the parameters passed to a Perl subroutine are accessible
only through the @_ array and thus appear to be a single array to the subroutine
that receives them.)</P>
<P>Using references, you can circumvent this limitation. If you create references
to each of the preceding arrays, you can easily pass two scalars to the subroutine
and then dereference the arrays those scalars have been assigned to, like this:</P>
<PRE><FONT COLOR="#0066FF">@array1 = (1, 3, 5);
@array2 = (2, 4, 6);
$ref1 = \@array1;
$ref2 = \@array2;
@sum = &array_adder($ref1, $ref2);
print "\@sum = (", join(`,',@sum), ")\n";
sub array_adder{
my($ref1, $ref2) = @_;
my $i = 0;
my @sum;
for($i = 0; $i <= $#{$ref1} ; $i++){
$sum[$i] = ${$ref1}[$i] + ${$ref2}[$i];
}
return @sum;
}
# prints: @sum = (3,7,11)
</FONT></PRE>
<P>Here, you've created a new array, whose elements are the sum of the individual
elements of two equal-length arrays' elements. That's easy, but you do it by passing
the arrays to a subroutine using references and thus make a formerly difficult, or
at least nonintuitive, task easier. In Perl4, you would have had to either use glob
types or have passed in the length of the arrays as the first or last argument and
then split @_ appropriately. Not pretty.</P>
<P>Note how you are able to use the reference within the subroutine in the $#array
context (the highest index of the array from zero-base), as well as access the individual
elements of the arrays that are being referred to. Again, this is just one single
use for references to arrays. See the documentation mentioned previously for many
more examples, PERLLOL for instance. <B><TT>References to Hashes (Associative Arrays)</TT></B>
When you create a reference to an associative array (hash), you can access all the
keys and values of the associative array through the reference. You can also use
the reference in place of the hash, using the syntax in Table 2.2, within any given
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -