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

📄 ch01_03.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 1.2. Establishing a Default Value (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:28:45Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch01_01.htm"TITLE="1. Strings"><LINKREL="prev"HREF="ch01_02.htm"TITLE="1.1. Accessing Substrings"><LINKREL="next"HREF="ch01_04.htm"TITLE="1.3. Exchanging Values Without Using Temporary Variables"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_02.htm"TITLE="1.1. Accessing Substrings"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 1.1. Accessing Substrings"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch01_01.htm"TITLE="1. Strings"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_04.htm"TITLE="1.3. Exchanging Values Without Using Temporary Variables"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 1.3. Exchanging Values Without Using Temporary Variables"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch01-chap01_establishing_0">1.2. Establishing a Default Value</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-289">Problem <ACLASS="indexterm"NAME="ch01-idx-1000010153-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010153-1"></A><ACLASS="indexterm"NAME="ch01-idx-1000010153-2"></A></A></H3><PCLASS="para">You would like to give a default value to a scalar variable, but only if it doesn't already have one. It often happens that you want a hard-coded default value for a variable that can be overridden from the command-line or through an environment variable.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-295">Solution</A></H3><PCLASS="para">Use the <CODECLASS="literal">||</CODE><ACLASS="indexterm"NAME="ch01-idx-1000010154-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010154-1"></A><ACLASS="indexterm"NAME="ch01-idx-1000010154-2"></A> or <CODECLASS="literal">||=</CODE> operator, which work on both strings and numbers:</P><PRECLASS="programlisting"># use $b if $b is true, else $c$a = $b || $c;              # set $x to $y unless $x is already true$x ||= $y</PRE><PCLASS="para">If <CODECLASS="literal">0</CODE> or &quot;<CODECLASS="literal">0</CODE>&quot; are valid values for your variables, use <CODECLASS="literal">defined</CODE><ACLASS="indexterm"NAME="ch01-idx-1000010160-0"></A> instead:</P><PRECLASS="programlisting"># use $b if $b is defined, else $c$a = defined($b) ? $b : $c;</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-317">Discussion</A></H3><PCLASS="para">The big difference between the two techniques (<CODECLASS="literal">defined</CODE> and <CODECLASS="literal">||</CODE>) is what they test: <ACLASS="indexterm"NAME="ch01-idx-1000010161-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010161-1"></A>definedness versus truth. Three defined values are still false in the world of Perl: <CODECLASS="literal">0</CODE>, &quot;<CODECLASS="literal">0</CODE>&quot;, and &quot;&quot;. If your variable already held one of those, and you wanted to keep that value, a <CODECLASS="literal">||</CODE> wouldn't work. You'd have to use the clumsier tests with <CODECLASS="literal">defined</CODE> instead. It's often convenient to arrange for your program to care only about true or false values, not defined or undefined ones.</P><PCLASS="para">Rather than being restricted in its return values to a mere 1 or 0 as in most other languages, Perl's <CODECLASS="literal">||</CODE> operator has a much more interesting property: It returns its first operand (the left-hand side) if that operand is true; otherwise it returns its second operand. The <CODECLASS="literal">&amp;&amp;</CODE><ACLASS="indexterm"NAME="ch01-idx-1000010175-0"></A> operator also returns the last evaluated expression, but is less often used for this property. These operators don't care whether their operands are strings, numbers, or references&nbsp;- any scalar will do. They just return the first one that makes the whole expression true or false. This doesn't affect the Boolean sense of the return value, but it does make the operators more convenient to use.</P><PCLASS="para">This property lets you provide a default value to a variable, function, or longer expression in case the first part doesn't pan out. Here's an example of <CODECLASS="literal">||</CODE>, which would set <CODECLASS="literal">$foo</CODE> to be the contents of either <CODECLASS="literal">$bar</CODE> or, if <CODECLASS="literal">$bar</CODE> is false, &quot;<CODECLASS="literal">DEFAULT</CODE> <CODECLASS="literal">VALUE</CODE>&quot;:</P><PRECLASS="programlisting">$foo = $bar || &quot;DEFAULT VALUE&quot;;</PRE><PCLASS="para">Here's another example, which sets <CODECLASS="literal">$dir</CODE> to be either the first argument to the program or &quot;<CODECLASS="literal">/tmp</CODE>&quot; if no argument was given.</P><PRECLASS="programlisting">$dir = shift(@ARGV) || &quot;/tmp&quot;;</PRE><PCLASS="para">We can do this without altering <CODECLASS="literal">@ARGV</CODE>:</P><PRECLASS="programlisting">$dir = $ARGV[0] || &quot;/tmp&quot;;</PRE><PCLASS="para">If <CODECLASS="literal">0</CODE> is a valid value for <CODECLASS="literal">$ARGV[0]</CODE>, we can't use <CODECLASS="literal">||</CODE> because it evaluates as false even though it's a value we want to accept. We must resort to the ternary ("hook") operator:</P><PRECLASS="programlisting">$dir = defined($ARGV[0]) ? shift(@ARGV) : &quot;/tmp&quot;;</PRE><PCLASS="para">We can also write this as follows, although with slightly different semantics:</P><PRECLASS="programlisting">$dir = @ARGV ? $ARGV[0] : &quot;/tmp&quot;;</PRE><PCLASS="para">This checks the number of elements in <CODECLASS="literal">@ARGV</CODE>. Using the hook operator as a condition in a <CODECLASS="literal">?:</CODE> statement evaluates <CODECLASS="literal">@ARGV</CODE> in scalar context. It's only false when there are 0 elements, in which case we use &quot;<CODECLASS="literal">/tmp</CODE>&quot;. In all other cases (when the user gives an argument), we use the first argument.</P><PCLASS="para">The following line increments a value in <CODECLASS="literal">%count</CODE>, using as the key either <CODECLASS="literal">$shell</CODE> or, if <CODECLASS="literal">$shell</CODE> is false, &quot;<CODECLASS="literal">/bin/sh</CODE>&quot;.</P><PRECLASS="programlisting">$count{ $shell || &quot;/bin/sh&quot; }++;</PRE><PCLASS="para">You may chain several alternatives together as we have in the following example. The first expression that returns a true value will be used.</P><PRECLASS="programlisting"># find the user name on Unix systems$user = $ENV{USER}     || $ENV{LOGNAME}     || getlogin()     || (getpwuid($&lt;))[0]     || &quot;Unknown uid number $&lt;&quot;;<CODECLASS="literal"></CODE><ACLASS="indexterm"NAME="ch01-idx-1000010166-0"></A></PRE><PCLASS="para">The <CODECLASS="literal">&amp;&amp;</CODE> operator works analogously: It returns its first operand if that operand is false; otherwise, it returns the second one. Because there aren't as many interesting false values as there are true ones, this property isn't used much. One use is demonstrated in Recipe 13.11 or 14.11.</P><PCLASS="para"><CODECLASS="literal"></CODE><ACLASS="indexterm"NAME="ch01-idx-1000010171-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010171-1"></A>The <CODECLASS="literal">||=</CODE> assignment operator looks odd, but it works exactly like the other binary assignment operators. For nearly all Perl's binary operators, <CODECLASS="literal">$VAR</CODE> <CODECLASS="literal">OP=</CODE> <CODECLASS="literal">VALUE</CODE> means <CODECLASS="literal">$VAR</CODE> <CODECLASS="literal">=</CODE> <CODECLASS="literal">$VAR</CODE> <CODECLASS="literal">OP</CODE> <CODECLASS="literal">VALUE</CODE>; for example, <CODECLASS="literal">$a</CODE> <CODECLASS="literal">+=</CODE> <CODECLASS="literal">$b</CODE> is the same as <CODECLASS="literal">$a</CODE> <CODECLASS="literal">=</CODE> <CODECLASS="literal">$a</CODE> <CODECLASS="literal">+</CODE> <CODECLASS="literal">$b</CODE>. So <CODECLASS="literal">||=</CODE> is used to set a variable when that variable is itself still false. Since the <CODECLASS="literal">||</CODE> check is a simple Boolean one&nbsp;- testing for truth&nbsp;- it doesn't care about undefined values even under <BCLASS="emphasis.bold">-w</B>.</P><PCLASS="para">Here's an example of <CODECLASS="literal">||=</CODE> that sets <CODECLASS="literal">$starting_point</CODE> to &quot;<CODECLASS="literal">Greenwich</CODE>&quot; unless it is already set. Again, we assume <CODECLASS="literal">$starting_point</CODE> won't have the value <CODECLASS="literal">0</CODE> or &quot;<CODECLASS="literal">0</CODE>&quot;, or that if it does, it's okay to change it.</P><PRECLASS="programlisting">$starting_point ||= &quot;Greenwich&quot;;</PRE><PCLASS="para">You can't use <CODECLASS="literal">or</CODE><ACLASS="indexterm"NAME="ch01-idx-1000010181-0"></A> in place of <CODECLASS="literal">||</CODE> in assignments because <CODECLASS="literal">or</CODE>'s precedence is too low. <CODECLASS="literal">$a</CODE> <CODECLASS="literal">=</CODE> <CODECLASS="literal">$b</CODE> <CODECLASS="literal">or</CODE> <CODECLASS="literal">$c</CODE> is equivalent to <CODECLASS="literal">($a</CODE> <CODECLASS="literal">=</CODE> <CODECLASS="literal">$b)</CODE> <CODECLASS="literal">or</CODE> <CODECLASS="literal">$c</CODE>. This will always assign <CODECLASS="literal">$b</CODE> to <CODECLASS="literal">$a</CODE>, which is not the behavior you want.</P><PCLASS="para">Don't extend this curious use of <CODECLASS="literal">||</CODE> and <CODECLASS="literal">||=</CODE> from scalars to arrays and hashes. It doesn't work because the operators put their left operand into scalar context. Instead, you must do something like this:</P><PRECLASS="programlisting">@a = @b unless @a;          # copy only if empty@a = @b ? @b : @c;          # assign @b if nonempty, else @c</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch01-pgfId-381">See Also</A></H3><PCLASS="para">The <CODECLASS="literal">||</CODE> operator in <EMCLASS="emphasis">perlop</EM> (1) or <ACLASS="olink"HREF="../prog/ch02_01.htm">Chapter 2</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A>; the <CODECLASS="literal">defined</CODE> and <CODECLASS="literal">exists</CODE> functions in <ICLASS="filename">perlfunc </I>(1) and <ACLASS="olink"HREF="../prog/ch03_01.htm">Chapter 3</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A><ACLASS="indexterm"NAME="ch01-idx-1000010156-0"></A><ACLASS="indexterm"NAME="ch01-idx-1000010156-1"></A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_02.htm"TITLE="1.1. Accessing Substrings"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 1.1. Accessing Substrings"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch01_04.htm"TITLE="1.3. Exchanging Values Without Using Temporary Variables"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 1.3. Exchanging Values Without Using Temporary Variables"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">1.1. Accessing Substrings</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">1.3. Exchanging Values Without Using Temporary Variables</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

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