⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch5.htm

📁 prrl 5 programs codes in the book
💻 HTM
📖 第 1 页 / 共 4 页
字号:
refereNCe. When parameters are called by refereNCe, changing their

value in the fuNCtion also changes their value in the main program.

Listing 5.2 shows how this happens.

<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>Create an array with 6 elements.<BR>

Print the elements of the array.<BR>

Call the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Print the elements of the array.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Change the values of the first two elements of </I><TT><I>@_</I></TT><I>.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 5.2&nbsp;&nbsp;05LST02.PL-Using the @Array to Show

Call by RefereNCe<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

@array = (0..5);

print(&quot;Before fuNCtion call, array = @array\n&quot;);

firstSub(@array);

print(&quot;After fuNCtion call, array =  @array\n&quot;);



sub firstSub{

    $_[0] = &quot;A&quot;;

    $_[1] = &quot;B&quot;;

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program prints:

<BLOCKQUOTE>

<PRE>

Before fuNCtion call, array =  0 1 2 3 4 5

After fuNCtion call, array =   A B 2 3 4 5

</PRE>

</BLOCKQUOTE>

<P>

You can see that the fuNCtion was able to affect the <TT>@array</TT>

variable in the main program. Generally, this is considered bad

programming practice because it does not isolate what the fuNCtion

does from the rest of the program. If you change the fuNCtion

so that scalars are used inside the fuNCtion, this problem goes

away. List-ing 5.3 shows how to redo the program in Listing 5.2

so scalars are used inside the fuNCtion.

<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>Create an array with 6 elements.<BR>

Print the elements of the array.<BR>

Call the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Print the elements of the array.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Assign the first two elements of </I><TT><I>@_</I></TT><I>

to </I><TT><I>$firstVar</I></TT><I>

and </I><TT><I>$secondVar</I></TT><I>.

<BR>

Change the values of the scalar variables.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 5.3&nbsp;&nbsp;05LST03.PL-Using Scalars Instead of

the @_ Array Inside FuNCtions<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

@array = (0..5);

print(&quot;Before fuNCtion call, array = @array\n&quot;);

firstSub(@array);

print(&quot;After fuNCtion call, array =  @array\n&quot;);



sub firstSub{

    ($firstVar, $secondVar) = @_ ;



    $firstVar = &quot;A&quot;;

    $secondVar = &quot;B&quot;;

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program prints:

<BLOCKQUOTE>

<PRE>

Before fuNCtion call, array =  0 1 2 3 4 5

After fuNCtion call, array =   0 1 2 3 4 5

</PRE>

</BLOCKQUOTE>

<P>

This example shows that the original <TT>@array</TT>

variable is left untouched. However, another problem has quietly

arisen. Let's change the program a little so the values of <TT>$firstVar</TT>

are printed before and after the fuNCtion call. Listing 5.4 shows

how changing a variable in the fuNCtion affects the main program.

<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>Assign a value to </I><TT><I>$firstVar</I></TT><I>.

<BR>

Create an array with 6 elements.<BR>

Print the elements of the array.<BR>

Call the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Print the elements of the array.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Assign the first two elements of </I><TT><I>@_</I></TT><I>

to </I><TT><I>$firstVar</I></TT><I>

and </I><TT><I>$secondVar</I></TT><I>.

<BR>

Change the values of the scalar variables.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 5.4&nbsp;&nbsp;05LST04.PL-Using Variables in FuNCtions

Can Cause Unexpected Results<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

$firstVar = 10;

@array    = (0..5);



print(&quot;Before fuNCtion call\n&quot;);

print(&quot;\tfirstVar = $firstVar\n&quot;);

print(&quot;\tarray    = @array\n&quot;);



firstSub(@array);



print(&quot;After fuNCtion call\n&quot;);

print(&quot;\tfirstVar = $firstVar\n&quot;);

print(&quot;\tarray    = @array\n&quot;);



sub firstSub{

    ($firstVar, $secondVar) = @_ ;



    $firstVar = &quot;A&quot;;

    $secondVar = &quot;B&quot;;

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program prints:

<BLOCKQUOTE>

<PRE>

Before fuNCtion call

        firstVar = 10

        array    = 0 1 2 3 4 5



After fuNCtion call

        firstVar = A

        array    = 0 1 2 3 4 5

</PRE>

</BLOCKQUOTE>

<P>

By using the <TT>$firstVar</TT> variable

in the fuNCtion you also change its value in the main program.

By default, all Perl variables are accessible everywhere inside

a program. This ability to globally access variables can be a

good thing at times. It does help when trying to isolate a fuNCtion

from the rest of your program. The next section shows you how

to create variables that can only be used inside fuNCtions.

<H3><A NAME="ExampleScopeofVariables">

Example: Scope of Variables</A></H3>

<P>

<I>Scope</I> refers to the visibility of variables. In other words,

which parts of your program can see or use it. Normally, every

variable has a global scope. ONCe defined, every part of your

program can access a variable.

<P>

It is very useful to be able to limit a variable's scope to a

single fuNCtion. In other words, the variable wil have a limited

scope. This way, changes inside the fuNCtion can't affect the

main program in unexpected ways. Listing 5.5 introduces two of

Perl's built-in fuNCtions that create variables of limited scope.

The <TT>my()</TT> fuNCtion creates

a variable that only the current fuNCtion can see. The <TT>local()</TT>

fuNCtion creates a variable that fuNCtions the current fuNCtion

calls can see. If that sounds confusing, don't worry. It is confusing;

but, Listing 5.5 should clear things up. In this case, it's a

listing that is worth a thousand words, not a picture!

<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 a two parameters.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Assign the first parameter to local variable </I><TT><I>$firstVar</I></TT><I>.

<BR>

Assign the second parameter to my variable </I><TT><I>$secondVar</I></TT><I>.

<BR>

Print the variables.<BR>

Call the second fuNCtion without any parameters.<BR>

Print the variables to see what changed.<BR>

Define the </I><TT><I>secondSub()</I></TT><I>

fuNCtion.<BR>

Print the variables.<BR>

Assign new values to the variables.<BR>

Print the variables to see that the new values were assigned correctly.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 5.5&nbsp;&nbsp;05LST05.PL-Using the Local and My FuNCtions

to Create Local Variables<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

firstSub(&quot;AAAAA&quot;, &quot;BBBBB&quot;);



sub firstSub{

    local ($firstVar) = $_[0];

    my($secondVar)    = $_[1];



    print(&quot;firstSub: firstVar  = $firstVar\n&quot;);

    print(&quot;firstSub: secondVar = $secondVar\n\n&quot;);



    secondSub();



    print(&quot;firstSub: firstVar  = $firstVar\n&quot;);

    print(&quot;firstSub: secondVar = $secondVar\n\n&quot;);

}



sub secondSub{

    print(&quot;secondSub: firstVar  = $firstVar\n&quot;);

    print(&quot;secondSub: secondVar = $secondVar\n\n&quot;);



    $firstVar  = &quot;ccccC&quot;;

    $secondVar = &quot;DDDDD&quot;;



    print(&quot;secondSub: firstVar  = $firstVar\n&quot;);

    print(&quot;secondSub: secondVar = $secondVar\n\n&quot;);

}

</PRE>

</BLOCKQUOTE>

<HR>

<P>

This program prints:

<BLOCKQUOTE>

<PRE>

firstSub: firstVar = AAAAA

firstSub: secondVar = BBBBB



secondSub: firstVar  = AAAAA

Use of uninitialized value at test.pl line 19.

secondSub: secondVar =



secondSub: firstVar  = ccccC

secondSub: secondVar = DDDDD



firstSub: firstVar  = ccccC

firstSub: secondVar = BBBBB

</PRE>

</BLOCKQUOTE>

<P>

The output from this example shows that <TT>secondSub()</TT>

could not access the <TT>$secondVar</TT>

variable that was created with <TT>my()</TT>

inside <TT>firstSub()</TT>. Perl even

prints out an error message that warns about the uninitialized

value. The <TT>$firstVar</TT> variable,

however, can be accessed and valued by <TT>secondSub()</TT>.

<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Tip</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

It's generally a better idea to use <TT>my()</TT> instead of <TT>local()</TT> so that you can tightly control the scope of local variables. Think about it this way-it's 4:00 in the morning and the project is due. Is that the time to be checking variable 
scope? No. Using <TT>my()</TT>enforces good programming practices and reduces headaches.

</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

Actually, the <TT>my()</TT> fuNCtion

is even more complex than I've said. The easy definition is that

it creates variables that only the current fuNCtion can see. The

true definition is that it creates variables with lexical scope.

This distiNCtion is only important when creating modules or objects,

so let's ignore the complicated definition for now. You'll hear

more about it in <A HREF="ch15.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch15.htm" >Chapter 15</A>, &quot;Perl Modules.&quot;

<P>

If you remember, I mentioned calling parameters by refereNCe.

Passing parameters by refereNCe means that fuNCtions can change

the variable's value, and the main program sees the change. When

<TT>local()</TT> is used in conjuNCtion

with assigning the <TT>@_ </TT>array

elements to scalars, then the parameters are essentially being

called by value. The fuNCtion can change the value of the variable,

but only the fuNCtion is affected. The rest of the program sees

the old value.

<H3><A NAME="ExampleUsingaListasaFuNCtionParameter">

Example: Using a List as a FuNCtion Parameter</A></H3>

<P>

Now that you understand about the scope of variables, let's take

another look at parameters. Because all parameters are passed

to a fuNCtion in one array, what if you need to pass both a scalar

and an array to the same fuNCtion? This next example shows you

what happens.

<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 the </I><TT><I>firstSub()</I></TT><I>

fuNCtion with two parameters: a list and a scalar.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Assign the elements of the </I><TT><I>@_</I></TT><I>

array to </I><TT><I>@</I></TT><I>array

and </I><TT><I>$firstVar</I></TT><I>.

<BR>

Print </I><TT><I>@array</I></TT><I>

and </I><TT><I>$firstVar</I></TT><I>.</I>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

firstSub((0..10), &quot;AAAA&quot;);



sub firstSub{

    local(@array, $firstVar) = @_ ;



    print(&quot;firstSub: array    = @array\n&quot;);

    print(&quot;firstSub: firstVar = $firstVar\n&quot;);

}

</PRE>

</BLOCKQUOTE>

<P>

This program prints:

<BLOCKQUOTE>

<PRE>

firstSub: array    = 0 1 2 3 4 5 6 7 8 9 10 AAAA

Use of uninitialized value at test.pl line 8.

firstSub: firstVar =

</PRE>

</BLOCKQUOTE>

<P>

When the local variables are initialized, the <TT>@array</TT>

variables grab all of the elements in the <TT>@</TT>

array, leaving none for the scalar variable. This results in the

uninitialized value message displayed in the output. You can fix

this by merely reversing the order of parameters. If the scalar

value comes first, then the fuNCtion processes the parameters

without a problem.

<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 the </I><TT><I>firstSub()</I></TT><I>

fuNCtion with two parameters: a scalar and a list.<BR>

Define the </I><TT><I>firstSub()</I></TT><I>

fuNCtion.<BR>

Assign the elements of the </I><TT><I>@_</I></TT><I>

array to </I><TT><I>$firstVar</I></TT><I>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -