📄 ch12_14.htm
字号:
<HTML><HEAD><TITLE>Recipe 12.13. Referring to Packages Indirectly (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen & Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly & Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:41:56Z"><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="ch12_01.htm"TITLE="12. Packages, Libraries, and Modules"><LINKREL="prev"HREF="ch12_13.htm"TITLE="12.12. Reporting Errors and Warnings Like Built-Ins"><LINKREL="next"HREF="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"></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="ch12_13.htm"TITLE="12.12. Reporting Errors and Warnings Like Built-Ins"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 12.12. Reporting Errors and Warnings Like Built-Ins"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch12_01.htm"TITLE="12. Packages, Libraries, and Modules"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 12.14. Using h2ph to Translate C #include Files"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch12-chap12_referring_0">12.13. Referring to Packages Indirectly</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1254">Problem<ACLASS="indexterm"NAME="ch12-idx-1000005271-0"></A><ACLASS="indexterm"NAME="ch12-idx-1000005271-1"></A><ACLASS="indexterm"NAME="ch12-idx-1000005271-2"></A></A></H3><PCLASS="para">You want to refer to a variable or function in a package unknown until runtime, but syntax like <CODECLASS="literal">$packname::$varname</CODE> is illegal.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1260">Solution</A></H3><PCLASS="para">Use <ACLASS="indexterm"NAME="ch12-idx-1000006220-0"></A>symbolic references:</P><PRECLASS="programlisting">{ no strict 'refs'; $val = ${ $packname . "::" . $varname }; @vals = @{ $packname . "::" . $aryname }; &{ $packname . "::" . $funcname }("args"); ($packname . "::" . $funcname) -> ("args");}</PRE></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1278">Discussion</A></H3><PCLASS="para">A package declaration has meaning at compile time. If you don't know the name of the package or variable until run time, you'll have to resort to symbolic references for direct access to the package symbol table. Assuming you normally run with <CODECLASS="literal">use</CODE> <CODECLASS="literal">strict</CODE> in effect, you must disable part of it to use symbolic references. Once you've used the <CODECLASS="literal">no</CODE> <CODECLASS="literal">strict</CODE> <CODECLASS="literal">'refs'</CODE> directive in that block, build up a string with the fully qualified name of the variable or function you're interested in. Then dereference this name as though it were a proper Perl reference.</P><PCLASS="para">Prior to version 5 of Perl, programmers were forced to use an <CODECLASS="literal">eval</CODE> for this kind of thing:</P><PRECLASS="programlisting">eval "package $packname; \$'$val = \$$varname"; # set $main'valdie if $@;</PRE><PCLASS="para">As you see, this approach makes quoting difficult. It's also comparatively slow. Fortunately, you never need to do this just to access variables indirectly by name. Symbolic references are a necessary compromise.</P><PCLASS="para">Similarly, <CODECLASS="literal">eval</CODE> could be used to define functions on the fly. Suppose you wanted to be able to get the base 2 or base 10 logs of numbers:</P><PRECLASS="programlisting">printf "log2 of 100 is %.2f\n", log2(100);printf "log10 of 100 is %.2f\n", log10(100);</PRE><PCLASS="para">Perl has only the natural log function. Here's how one could use <CODECLASS="literal">eval</CODE> to create these functions at run time. Here we'll create functions named <CODECLASS="literal">log2</CODE> up through <CODECLASS="literal">log999</CODE>:</P><PRECLASS="programlisting">$packname = 'main';for ($i = 2; $i < 1000; $i++) { $logN = log($i); eval "sub ${packname}::log$i { log(shift) / $logN }"; die if $@;}</PRE><PCLASS="para">Here, at least, you don't need to do that. The following code does the same thing, but instead of compiling a new function 998 times, we compile it only once, as a <ACLASS="indexterm"NAME="ch12-idx-1000006217-0"></A>closure. Then we use symbolic dereferencing of the symbol table to assign the same subroutine <ACLASS="indexterm"NAME="ch12-idx-1000006221-0"></A>reference to many function names:</P><PRECLASS="programlisting">$packname = 'main';for ($i = 2; $i < 1000; $i++) { my $logN = log($i); no strict 'refs'; *{"${packname}::log$i"} = sub { log(shift) / $logN };}</PRE><PCLASS="para">When you assign a reference to a typeglob, you create an alias just for the type of that name. That's how the Exporter does its job. The first line in the next code sample manually imports the function name <CODECLASS="literal">Colors::blue</CODE> into the current package. The second makes the <CODECLASS="literal">main::blue</CODE> function an alias for the <CODECLASS="literal">Colors::azure</CODE> function.</P><PRECLASS="programlisting">*blue = \&Colors::blue;*main::blue = \&Colors::azure;</PRE><PCLASS="para">Given the flexibility of typeglob assignments and symbolic references, a full-blown <CODECLASS="literal">eval</CODE> <CODECLASS="literal">"STRING"</CODE> is nearly always unnecessary, the last resort of the desperate programmer. The only thing worse would be if it weren't available at all.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch12-pgfId-1334">See Also</A></H3><PCLASS="para">The section on <ACLASS="olink"HREF="../prog/ch04_04.htm">"Symbolic References"</A> in <ACLASS="olink"HREF="../prog/ch04_01.htm">Chapter 4</A> of <ACLASS="citetitle"HREF="../prog/index.htm"TITLE="Programming Perl"><CITECLASS="citetitle">Programming Perl</CITE></A> and in the start of <ICLASS="filename">perlsub </I>(1); <ACLASS="xref"HREF="ch11_05.htm"TITLE="Taking References to Functions">Recipe 11.4</A><ACLASS="indexterm"NAME="ch12-idx-1000005273-0"></A><ACLASS="indexterm"NAME="ch12-idx-1000005273-1"></A><ACLASS="indexterm"NAME="ch12-idx-1000005273-2"></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="ch12_13.htm"TITLE="12.12. Reporting Errors and Warnings Like Built-Ins"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 12.12. Reporting Errors and Warnings Like Built-Ins"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="ch12_15.htm"TITLE="12.14. Using h2ph to Translate C #include Files"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 12.14. Using h2ph to Translate C #include Files"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">12.12. Reporting Errors and Warnings Like Built-Ins</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">12.14. Using h2ph to Translate C #include Files</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 © 2002</a> O'Reilly & 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 + -