📄 perlmod.1
字号:
\& *dick = \e$richard;.Ve.PPWhich makes \f(CW$richard\fR and \f(CW$dick\fR the same variable, but leaves\&\f(CW@richard\fR and \f(CW@dick\fR as separate arrays. Tricky, eh?.PPThere is one subtle difference between the following statements:.PP.Vb 2\& *foo = *bar;\& *foo = \e$bar;.Ve.PP\&\f(CW\*(C`*foo = *bar\*(C'\fR makes the typeglobs themselves synonymous while\&\f(CW\*(C`*foo = \e$bar\*(C'\fR makes the \s-1SCALAR\s0 portions of two distinct typeglobsrefer to the same scalar value. This means that the following code:.PP.Vb 2\& $bar = 1;\& *foo = \e$bar; # Make $foo an alias for $bar\&\& {\& local $bar = 2; # Restrict changes to block\& print $foo; # Prints \*(Aq1\*(Aq!\& }.Ve.PPWould print '1', because \f(CW$foo\fR holds a reference to the \fIoriginal\fR\&\f(CW$bar\fR \*(-- the one that was stuffed away by \f(CW\*(C`local()\*(C'\fR and which will berestored when the block ends. Because variables are accessed through thetypeglob, you can use \f(CW\*(C`*foo = *bar\*(C'\fR to create an alias which can belocalized. (But be aware that this means you can't have a separate\&\f(CW@foo\fR and \f(CW@bar\fR, etc.).PPWhat makes all of this important is that the Exporter module uses globaliasing as the import/export mechanism. Whether or not you can properlylocalize a variable that has been exported from a module depends on howit was exported:.PP.Vb 2\& @EXPORT = qw($FOO); # Usual form, can\*(Aqt be localized\& @EXPORT = qw(*FOO); # Can be localized.Ve.PPYou can work around the first case by using the fully qualified name(\f(CW$Package::FOO\fR) where you need a local value, or by overriding itby saying \f(CW\*(C`*FOO = *Package::FOO\*(C'\fR in your script..PPThe \f(CW\*(C`*x = \e$y\*(C'\fR mechanism may be used to pass and return cheap referencesinto or from subroutines if you don't want to copy the wholething. It only works when assigning to dynamic variables, notlexicals..PP.Vb 9\& %some_hash = (); # can\*(Aqt be my()\& *some_hash = fn( \e%another_hash );\& sub fn {\& local *hashsym = shift;\& # now use %hashsym normally, and you\& # will affect the caller\*(Aqs %another_hash\& my %nhash = (); # do what you want\& return \e%nhash;\& }.Ve.PPOn return, the reference will overwrite the hash slot in thesymbol table specified by the *some_hash typeglob. Thisis a somewhat tricky way of passing around references cheaplywhen you don't want to have to remember to dereference variablesexplicitly..PPAnother use of symbol tables is for making \*(L"constant\*(R" scalars..IX Xref "constant scalar, constant".PP.Vb 1\& *PI = \e3.14159265358979;.Ve.PPNow you cannot alter \f(CW$PI\fR, which is probably a good thing all in all.This isn't the same as a constant subroutine, which is subject tooptimization at compile-time. A constant subroutine is one prototypedto take no arguments and to return a constant expression. Seeperlsub for details on these. The \f(CW\*(C`use constant\*(C'\fR pragma is aconvenient shorthand for these..PPYou can say \f(CW*foo{PACKAGE}\fR and \f(CW*foo{NAME}\fR to find out what name andpackage the *foo symbol table entry comes from. This may be usefulin a subroutine that gets passed typeglobs as arguments:.PP.Vb 6\& sub identify_typeglob {\& my $glob = shift;\& print \*(AqYou gave me \*(Aq, *{$glob}{PACKAGE}, \*(Aq::\*(Aq, *{$glob}{NAME}, "\en";\& }\& identify_typeglob *foo;\& identify_typeglob *bar::baz;.Ve.PPThis prints.PP.Vb 2\& You gave me main::foo\& You gave me bar::baz.Ve.PPThe \f(CW*foo{THING}\fR notation can also be used to obtain references to theindividual elements of *foo. See perlref..PPSubroutine definitions (and declarations, for that matter) neednot necessarily be situated in the package whose symbol table theyoccupy. You can define a subroutine outside its package byexplicitly qualifying the name of the subroutine:.PP.Vb 2\& package main;\& sub Some_package::foo { ... } # &foo defined in Some_package.Ve.PPThis is just a shorthand for a typeglob assignment at compile time:.PP.Vb 1\& BEGIN { *Some_package::foo = sub { ... } }.Ve.PPand is \fInot\fR the same as writing:.PP.Vb 4\& {\& package Some_package;\& sub foo { ... }\& }.Ve.PPIn the first two versions, the body of the subroutine islexically in the main package, \fInot\fR in Some_package. Sosomething like this:.PP.Vb 1\& package main;\&\& $Some_package::name = "fred";\& $main::name = "barney";\&\& sub Some_package::foo {\& print "in ", _\|_PACKAGE_\|_, ": \e$name is \*(Aq$name\*(Aq\en";\& }\&\& Some_package::foo();.Ve.PPprints:.PP.Vb 1\& in main: $name is \*(Aqbarney\*(Aq.Ve.PPrather than:.PP.Vb 1\& in Some_package: $name is \*(Aqfred\*(Aq.Ve.PPThis also has implications for the use of the \s-1SUPER::\s0 qualifier(see perlobj)..Sh "\s-1BEGIN\s0, \s-1UNITCHECK\s0, \s-1CHECK\s0, \s-1INIT\s0 and \s-1END\s0".IX Xref "BEGIN UNITCHECK CHECK INIT END".IX Subsection "BEGIN, UNITCHECK, CHECK, INIT and END"Five specially named code blocks are executed at the beginning and atthe end of a running Perl program. These are the \f(CW\*(C`BEGIN\*(C'\fR,\&\f(CW\*(C`UNITCHECK\*(C'\fR, \f(CW\*(C`CHECK\*(C'\fR, \f(CW\*(C`INIT\*(C'\fR, and \f(CW\*(C`END\*(C'\fR blocks..PPThese code blocks can be prefixed with \f(CW\*(C`sub\*(C'\fR to give the appearance of asubroutine (although this is not considered good style). One should notethat these code blocks don't really exist as named subroutines (despitetheir appearance). The thing that gives this away is the fact that you canhave \fBmore than one\fR of these code blocks in a program, and they will get\&\fBall\fR executed at the appropriate moment. So you can't execute any ofthese code blocks by name..PPA \f(CW\*(C`BEGIN\*(C'\fR code block is executed as soon as possible, that is, the momentit is completely defined, even before the rest of the containing file (orstring) is parsed. You may have multiple \f(CW\*(C`BEGIN\*(C'\fR blocks within a file (oreval'ed string) \*(-- they will execute in order of definition. Because a \f(CW\*(C`BEGIN\*(C'\fRcode block executes immediately, it can pull in definitions of subroutinesand such from other files in time to be visible to the rest of the compileand run time. Once a \f(CW\*(C`BEGIN\*(C'\fR has run, it is immediately undefined and anycode it used is returned to Perl's memory pool..PPIt should be noted that \f(CW\*(C`BEGIN\*(C'\fR and \f(CW\*(C`UNITCHECK\*(C'\fR code blocks \fBare\fRexecuted inside string \f(CW\*(C`eval()\*(C'\fR's. The \f(CW\*(C`CHECK\*(C'\fR and \f(CW\*(C`INIT\*(C'\fR codeblocks are \fBnot\fR executed inside a string eval, which e.g. can be aproblem in a mod_perl environment..PPAn \f(CW\*(C`END\*(C'\fR code block is executed as late as possible, that is, afterperl has finished running the program and just before the interpreteris being exited, even if it is exiting as a result of a \fIdie()\fR function.(But not if it's morphing into another program via \f(CW\*(C`exec\*(C'\fR, orbeing blown out of the water by a signal\*(--you have to trap that yourself(if you can).) You may have multiple \f(CW\*(C`END\*(C'\fR blocks within a file\*(--theywill execute in reverse order of definition; that is: last in, firstout (\s-1LIFO\s0). \f(CW\*(C`END\*(C'\fR blocks are not executed when you run perl with the\&\f(CW\*(C`\-c\*(C'\fR switch, or if compilation fails..PPNote that \f(CW\*(C`END\*(C'\fR code blocks are \fBnot\fR executed at the end of a string\&\f(CW\*(C`eval()\*(C'\fR: if any \f(CW\*(C`END\*(C'\fR code blocks are created in a string \f(CW\*(C`eval()\*(C'\fR,they will be executed just as any other \f(CW\*(C`END\*(C'\fR code block of that packagein \s-1LIFO\s0 order just before the interpreter is being exited..PPInside an \f(CW\*(C`END\*(C'\fR code block, \f(CW$?\fR contains the value that the program isgoing to pass to \f(CW\*(C`exit()\*(C'\fR. You can modify \f(CW$?\fR to change the exitvalue of the program. Beware of changing \f(CW$?\fR by accident (e.g. byrunning something via \f(CW\*(C`system\*(C'\fR)..IX Xref "$?".PP\&\f(CW\*(C`UNITCHECK\*(C'\fR, \f(CW\*(C`CHECK\*(C'\fR and \f(CW\*(C`INIT\*(C'\fR code blocks are useful to catch thetransition between the compilation phase and the execution phase ofthe main program..PP\&\f(CW\*(C`UNITCHECK\*(C'\fR blocks are run just after the unit which defined them hasbeen compiled. The main program file and each module it loads arecompilation units, as are string \f(CW\*(C`eval\*(C'\fRs, code compiled using the\&\f(CW\*(C`(?{ })\*(C'\fR construct in a regex, calls to \f(CW\*(C`do FILE\*(C'\fR, \f(CW\*(C`require FILE\*(C'\fR,and code after the \f(CW\*(C`\-e\*(C'\fR switch on the command line..PP\&\f(CW\*(C`CHECK\*(C'\fR code blocks are run just after the \fBinitial\fR Perl compile phase endsand before the run time begins, in \s-1LIFO\s0 order. \f(CW\*(C`CHECK\*(C'\fR code blocks are usedin the Perl compiler suite to save the compiled state of the program..PP\&\f(CW\*(C`INIT\*(C'\fR blocks are run just before the Perl runtime begins execution, in\&\*(L"first in, first out\*(R" (\s-1FIFO\s0) order..PPWhen you use the \fB\-n\fR and \fB\-p\fR switches to Perl, \f(CW\*(C`BEGIN\*(C'\fR and\&\f(CW\*(C`END\*(C'\fR work just as they do in \fBawk\fR, as a degenerate case.Both \f(CW\*(C`BEGIN\*(C'\fR and \f(CW\*(C`CHECK\*(C'\fR blocks are run when you use the \fB\-c\fRswitch for a compile-only syntax check, although your main codeis not..PPThe \fBbegincheck\fR program makes it all clear, eventually:.PP.Vb 1\& #!/usr/bin/perl\&\& # begincheck\&\& print "10. Ordinary code runs at runtime.\en";\&\& END { print "16. So this is the end of the tale.\en" }\& INIT { print " 7. INIT blocks run FIFO just before runtime.\en" }\& UNITCHECK {\& print " 4. And therefore before any CHECK blocks.\en"\& }\& CHECK { print " 6. So this is the sixth line.\en" }\&\& print "11. It runs in order, of course.\en";\&\& BEGIN { print " 1. BEGIN blocks run FIFO during compilation.\en" }\& END { print "15. Read perlmod for the rest of the story.\en" }\& CHECK { print " 5. CHECK blocks run LIFO after all compilation.\en" }\& INIT { print " 8. Run this again, using Perl\*(Aqs \-c switch.\en" }\&\& print "12. This is anti\-obfuscated code.\en";\&\& END { print "14. END blocks run LIFO at quitting time.\en" }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -