📄 ch8.htm
字号:
<HTML>
<HEAD>
<TITLE>Chapter 8 -- RefereNCes</TITLE>
<META>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#CE2910">
<H1><FONT SIZE=6 COLOR=#FF0000>Chapter 8</FONT></H1>
<H1><FONT SIZE=6 COLOR=#FF0000>RefereNCes</FONT></H1>
<HR>
<P>
<CENTER><B><FONT SIZE=5>CONTENTS</FONT></B></CENTER>
<UL>
<LI><A HREF="#RefereNCeTypes">
RefereNCe Types</A>
<UL>
<LI><A HREF="#ExamplePassingParameterstoFuNCtions">
Example: Passing Parameters to FuNCtions</A>
<LI><A HREF="#ExampleTherefFuNCtion">
Example: The ref() FuNCtion</A>
<LI><A HREF="#ExampleCreatingaDataRecord">
Example: Creating a Data Record</A>
<LI><A HREF="#ExampleInterpolatingFuNCtionsInsideDoubleQuotedStrings">
Example: Interpolating FuNCtions Inside Double-Quoted Strings
</A>
</UL>
<LI><A HREF="#Summary">
Summary</A>
<LI><A HREF="#ReviewQuestions">
Review Questions</A>
<LI><A HREF="#ReviewExercises">
Review Exercises</A>
</UL>
<HR>
<P>
A <I>refereNCe</I> is a scalar value that points to a memory location
that holds some type of data. Everything in your Perl program
is stored inside your computer's memory. Therefore, all of your
variables and fuNCtions are located at some memory location. RefereNCes
are used to hold the memory addresses. When a refereNCe is <I>derefereNCed</I>,
you retrieve the information referred to by the refereNCe.
<H2><A NAME="RefereNCeTypes"><FONT SIZE=5 COLOR=#FF0000>
RefereNCe Types</FONT></A></H2>
<P>
There are six types of refereNCes. A refereNCe can point to a
scalar, an array, a hash, a glob, a fuNCtion, or another refereNCe.
Table 8.1 shows how the different types are valued with the assignment
operator and how to derefereNCe them using curly braces.<BR>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
I briefly mentioned hashes in <A HREF="ch3.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch3.htm" >Chapter 3</A> "Variables." Just to refresh your memory, hashes are another name for associative arrays. Because "hash" is shorter than "associative array," I'll be using both
terms in this chapter.</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
<CENTER><B>Table 8.1 The Six Types of RefereNCes</B></CENTER>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD WIDTH=253><I>RefereNCe Assignment</I></TD><TD WIDTH=337><I>How to DerefereNCe</I>
</TD></TR>
<TR><TD WIDTH=253><TT>$refScalar</TT> = <TT>\$scalar;</TT>
</TD><TD WIDTH=337><TT>${$refScalar}</TT> is a scalar value.
</TD></TR>
<TR><TD WIDTH=253><TT>$refArray</TT> = <TT>\@array;</TT>
</TD><TD WIDTH=337><TT>@{$refArray}</TT> is an array value.
</TD></TR>
<TR><TD WIDTH=253><TT>$refHash</TT> = <TT>\%hash;</TT>
</TD><TD WIDTH=337><TT>%{$refHash}</TT> is a hash value.
</TD></TR>
<TR><TD WIDTH=253><TT>$refglob</TT> = <TT>\*file;</TT>
</TD><TD WIDTH=337>Glob refereNCes are beyond the scope of this book, but a short example can be found at <B>http://www. mtolive.com/pbc/ch08.htm#Josh Purinton</B>.
</TD></TR>
<TR><TD WIDTH=253><TT>$refFuNCtion</TT> = <TT>\&fuNCtion;</TT>
</TD><TD WIDTH=337><TT>&{$refFuNCtion}</TT> is a fuNCtion location.
</TD></TR>
<TR><TD WIDTH=253><TT>$refRef</TT> = <TT>\$refScalar;</TT>
</TD><TD WIDTH=337><TT>${${$refScalar}</TT> is a scalar value.
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
Essentially, all you need to do in order to create a refereNCe
is to add the backslash to the front of a value or variable.
<H3><A NAME="ExamplePassingParameterstoFuNCtions">
Example: Passing Parameters to FuNCtions</A></H3>
<P>
Back in <A HREF="ch5.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch5.htm" >Chapter 5</A> "FuNCtions," we talked about passing
parameters to fuNCtions. At the time, we were not able to pass
more than one array to a fuNCtion. This was because fuNCtions
only see one array (the <TT>@_</TT>
array) when looking for parameters. RefereNCes can be used to
overcome this limitation.
<P>
Let's start off by passing two arrays into a fuNCtion to show
that the fuNCtion only sees one array.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Call </I><TT><I>firstSub()</I></TT><I>
with two arrays as parameters.<BR>
Define the </I><TT><I>firstSub()</I></TT><I>
fuNCtion.<BR>
Create local variables and assign elements from the parameter
array to them.<BR>
Print the local arrays.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
firstSub( (1..5), ("A".."E"));
sub firstSub {
my(@firstArray, @secondArray) = @_ ;
print("The first array is @firstArray.\n");
print("The second array is @secondArray.\n");
}
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
The first array is 1 2 3 4 5 A B C D E.
The second array is .
</PRE>
</BLOCKQUOTE>
<P>
Inside the <TT>firstSub()</TT> fuNCtion,
the <TT>@firstArray</TT> variable
was assigned the entire parameter array, leaving nothing for the
<TT>@secondArray</TT> variable. By
passing refereNCes to <TT>@arrayOne</TT>
and <TT>@arrayTwo</TT>, we can preserve
the arrays for use inside the fuNCtion. Very few changes are needed
to enable the above example to use refereNCes. Take a look.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Call </I><TT><I>firstSub()</I></TT><I>
using the backslash operator to pass a refereNCe to each array.
<BR>
Define the </I><TT><I>firstSub()</I></TT><I>
fuNCtion.<BR>
Create two local scalar variables to hold the array refereNCes.
<BR>
Print the local variables, derefereNCing them to look like arrays.
This is done using the @{} notation.</I>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
firstSub( \(1..5), \("A".."E") ); # One
sub firstSub {
my($ref_firstArray, $ref_secondArray) = @_ ; # Two
print("The first array is @{$ref_firstArray}.\n"); # Three
print("The second array is @{$ref_secondArray}.\n"); # Three
}
</PRE>
</BLOCKQUOTE>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
The first array is 1 2 3 4 5.
The second array is A B C D E.
</PRE>
</BLOCKQUOTE>
<P>
Three things were done to make this example use refereNCes:
<OL>
<LI>In the line marked "One," backslashes were added
to indicate that a refereNCe to the array should be passed.
<LI>In the line marked "Two," the refereNCes were taken
from the parameter array and assigned to scalar variables.
<LI>In the lines marked "Three," the scalar values were
derefereNCed. DerefereNCing means that Perl will use the refereNCe
as if it were a normal data type-in this case, an array variable.
</OL>
<H3><A NAME="ExampleTherefFuNCtion">
Example: The ref() FuNCtion</A></H3>
<P>
Using refereNCes to pass arrays into a fuNCtion worked well and
it was easy, wasn't it? However, what happens if you pass a scalar
refereNCe to the <TT>firstSub()</TT>
fuNCtion instead of an array refereNCe? Listing 8.1 shows how
passing a scalar refereNCe when the fuNCtion demands an array
refereNCe causes problems.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Call </I><TT><I>firstSub()</I></TT><I>
and pass a refereNCe to a scalar and a refereNCe to an array.
<BR>
Define the </I><TT><I>firstSub()</I></TT><I>
fuNCtion.<BR>
Create two local scalar variables to hold the array refereNCes.
<BR>
Print the local variables, derefereNCing them to look like arrays.</I>
</BLOCKQUOTE>
<HR>
<BLOCKQUOTE>
<B>Listing 8.1 08LST01.PL-Passing a Scalar RefereNCe
When the FuNCtion Demands an Array RefereNCe Causes Problems<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
firstSub( \10, \("A".."E") );
sub firstSub {
my($ref_firstArray, $ref_secondArray) = @_ ;
print("The first array is @{$ref_firstArray}.\n");
print("The second array is @{$ref_secondArray}.\n");
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
Not an ARRAY refereNCe at 08lst01.pl line 9.
</PRE>
</BLOCKQUOTE>
<P>
Perl provides the <TT>ref()</TT> fuNCtion
so that you can check the refereNCe type before derefereNCing
a refereNCe. The next example shows how to trap the mistake of
passing a scalar refereNCe instead of an array refereNCe.
<P>
<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>
<BLOCKQUOTE>
<I>Call </I><TT><I>firstSub()</I></TT><I>
and pass a refereNCe to each variable.<BR>
Define the </I><TT><I>firstSub()</I></TT><I>
fuNCtion.<BR>
Create two local scalar variables to hold the array refereNCes.
<BR>
Print the local variables if each variable is a refereNCe to an
array. Otherwise, print nothing.</I>
</BLOCKQUOTE>
<P>
Listing 8.2 shows how to test for an Array RefereNCe passed as
a parameter.
<HR>
<BLOCKQUOTE>
<B>Listing 8.2 08LST02.PL-How to Test for an Array
RefereNCe Passed as a Parameter<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<PRE>
firstSub( \10, \("A".."E") );
sub firstSub {
my($ref_firstArray, $ref_secondArray) = @_ ;
print("The first array is @{$ref_firstArray}.\n")
if (ref($ref_firstArray) eq "ARRAY"); # One
print("The second array is @{$ref_secondArray}.\n"
if (ref($ref_secondArray) eq "ARRAY"); # Two
}
</PRE>
</BLOCKQUOTE>
<HR>
<P>
This program displays:
<BLOCKQUOTE>
<PRE>
The second array is 1 2 3 4 5.
</PRE>
</BLOCKQUOTE>
<P>
Only the second parameter is printed because the first parameter-the
scalar refereNCe-failed the test on the line marked "One."
The statement modifiers on the lines marked "One" and
"Two" ensure that we are derefereNCing an array refereNCe.
This prevents the error message that appeared earlier. Of course,
in your own programs you might want to set an error flag or print
a warning.
<P>
For more information about statement modifiers, see <A HREF="ch6.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch6.htm" >Chapter 6</A>
"Statements."
<P>
Table 8.2 shows some values that the ref() fuNCtion can return.
<BR>
<P>
<CENTER><B>Table 8.2 Using the ref() FuNCtion</B></CENTER>
<p>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD WIDTH=163><I>FuNCtion Call</I></TD><TD WIDTH=138><I>Return Value</I>
</TD></TR>
<TR><TD WIDTH=163>ref( 10 );</TD><TD WIDTH=138>undefined</TD>
</TR>
<TR><TD WIDTH=163>ref( \10 );</TD><TD WIDTH=138>SCALAR</TD></TR>
<TR><TD WIDTH=163>ref( \{1 => "Joe"} );</TD><TD WIDTH=138>HASH
</TD></TR>
<TR><TD WIDTH=163>ref( \&firstSub );</TD><TD WIDTH=138>CODE
</TD></TR>
<TR><TD WIDTH=163>ref( \\10 );</TD><TD WIDTH=138>REF</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
Listing 8.3 shows another example of the <TT>ref()</TT>
fuNCtion in action.
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -