diff options
Diffstat (limited to 'pod/perlfaq7.pod')
-rw-r--r-- | pod/perlfaq7.pod | 196 |
1 files changed, 169 insertions, 27 deletions
diff --git a/pod/perlfaq7.pod b/pod/perlfaq7.pod index e1bccc883f..070d9653d4 100644 --- a/pod/perlfaq7.pod +++ b/pod/perlfaq7.pod @@ -1,6 +1,6 @@ =head1 NAME -perlfaq7 - Perl Language Issues ($Revision: 1.21 $, $Date: 1998/06/22 15:20:07 $) +perlfaq7 - Perl Language Issues ($Revision: 1.28 $, $Date: 1999/05/23 20:36:18 $) =head1 DESCRIPTION @@ -18,19 +18,17 @@ In the words of Chaim Frenkel: "Perl's grammar can not be reduced to BNF. The work of parsing perl is distributed between yacc, the lexer, smoke and mirrors." -=head2 What are all these $@%* punctuation signs, and how do I know when to use them? +=head2 What are all these $@%&* punctuation signs, and how do I know when to use them? They are type specifiers, as detailed in L<perldata>: $ for scalar values (number, string or reference) @ for arrays % for hashes (associative arrays) + & for subroutines (aka functions, procedures, methods) * for all types of that symbol name. In version 4 you used them like pointers, but in modern perls you can just use references. -While there are a few places where you don't actually need these type -specifiers, you should always use them. - A couple of others that you're likely to encounter that aren't really type specifiers are: @@ -180,7 +178,7 @@ own module. Make sure to change the names appropriately. # if using RCS/CVS, this next line may be preferred, # but beware two-digit versions. - $VERSION = do{my@r=q$Revision: 1.21 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r}; + $VERSION = do{my@r=q$Revision: 1.28 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r}; @ISA = qw(Exporter); @EXPORT = qw(&func1 &func2 &func3); @@ -229,6 +227,10 @@ own module. Make sure to change the names appropriately. 1; # modules must return true +The h2xs program will create stubs for all the important stuff for you: + + % h2xs -XA -n My::Module + =head2 How do I create a class? See L<perltoot> for an introduction to classes and objects, as well as @@ -313,7 +315,7 @@ caller's scope. Variable suicide is when you (temporarily or permanently) lose the value of a variable. It is caused by scoping through my() and local() -interacting with either closures or aliased foreach() interator +interacting with either closures or aliased foreach() iterator variables and subroutine arguments. It used to be easy to inadvertently lose a variable's value this way, but now it's much harder. Take this code: @@ -326,12 +328,13 @@ harder. Take this code: print "Finally $f\n"; The $f that has "bar" added to it three times should be a new C<$f> -(C<my $f> should create a new local variable each time through the -loop). It isn't, however. This is a bug, and will be fixed. +(C<my $f> should create a new local variable each time through the loop). +It isn't, however. This was a bug, now fixed in the latest releases +(tested against 5.004_05, 5.005_03, and 5.005_56). -=head2 How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regexp}? +=head2 How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}? -With the exception of regexps, you need to pass references to these +With the exception of regexes, you need to pass references to these objects. See L<perlsub/"Pass by Reference"> for this particular question, and L<perlref> for information on references. @@ -344,7 +347,7 @@ reference to an existing or anonymous variable or function: func( \$some_scalar ); - func( \$some_array ); + func( \@some_array ); func( [ 1 .. 10 ] ); func( \%some_hash ); @@ -387,28 +390,42 @@ If you're planning on generating new filehandles, you could do this: $fh = openit('< /etc/motd'); print <$fh>; -=item Passing Regexps +=item Passing Regexes + +To pass regexes around, you'll need to be using a release of Perl +sufficiently recent as to support the C<qr//> construct, pass around +strings and use an exception-trapping eval, or else be very, very clever. + +Here's an example of how to pass in a string to be regex compared +using C<qr//>: -To pass regexps around, you'll need to either use one of the highly -experimental regular expression modules from CPAN (Nick Ing-Simmons's -Regexp or Ilya Zakharevich's Devel::Regexp), pass around strings -and use an exception-trapping eval, or else be be very, very clever. -Here's an example of how to pass in a string to be regexp compared: + sub compare($$) { + my ($val1, $regex) = @_; + my $retval = $val1 =~ /$regex/; + return $retval; + } + $match = compare("old McDonald", qr/d.*D/i); + +Notice how C<qr//> allows flags at the end. That pattern was compiled +at compile time, although it was executed later. The nifty C<qr//> +notation wasn't introduced until the 5.005 release. Before that, you +had to approach this problem much less intuitively. For example, here +it is again if you don't have C<qr//>: sub compare($$) { - my ($val1, $regexp) = @_; - my $retval = eval { $val =~ /$regexp/ }; + my ($val1, $regex) = @_; + my $retval = eval { $val1 =~ /$regex/ }; die if $@; return $retval; } - $match = compare("old McDonald", q/d.*D/); + $match = compare("old McDonald", q/($?i)d.*D/); Make sure you never say something like this: - return eval "\$val =~ /$regexp/"; # WRONG + return eval "\$val =~ /$regex/"; # WRONG -or someone can sneak shell escapes into the regexp due to the double +or someone can sneak shell escapes into the regex due to the double interpolation of the eval and the double-quoted string. For example: $pattern_of_evil = 'danger ${ system("rm -rf * &") } danger'; @@ -484,7 +501,7 @@ could conceivably have several packages in that same file all accessing the same private variable, but another file with the same package couldn't get to it. -See L<perlsub/"Peristent Private Variables"> for details. +See L<perlsub/"Persistent Private Variables"> for details. =head2 What's the difference between dynamic and lexical (static) scoping? Between local() and my()? @@ -563,7 +580,7 @@ However, dynamic variables (aka global, local, or package variables) are effectively shallowly bound. Consider this just one more reason not to use them. See the answer to L<"What's a closure?">. -=head2 Why doesn't "my($foo) = <FILE>;" work right? +=head2 Why doesn't "my($foo) = E<lt>FILEE<gt>;" work right? C<my()> and C<local()> give list context to the right hand side of C<=>. The E<lt>FHE<gt> read operation, like so many of Perl's @@ -626,7 +643,7 @@ where they don't belong. This is explained in more depth in the L<perlsyn>. Briefly, there's no official case statement, because of the variety of tests possible in Perl (numeric comparison, string comparison, glob comparison, -regexp matching, overloaded comparisons, ...). Larry couldn't decide +regex matching, overloaded comparisons, ...). Larry couldn't decide how best to do this, so he left it out, even though it's been on the wish list since perl1. @@ -797,9 +814,134 @@ This can't go just anywhere. You have to put a pod directive where the parser is expecting a new statement, not just in the middle of an expression or some other arbitrary yacc grammar production. +=head2 How do I clear a package? + +Use this code, provided by Mark-Jason Dominus: + + sub scrub_package { + no strict 'refs'; + my $pack = shift; + die "Shouldn't delete main package" + if $pack eq "" || $pack eq "main"; + my $stash = *{$pack . '::'}{HASH}; + my $name; + foreach $name (keys %$stash) { + my $fullname = $pack . '::' . $name; + # Get rid of everything with that name. + undef $$fullname; + undef @$fullname; + undef %$fullname; + undef &$fullname; + undef *$fullname; + } + } + +Or, if you're using a recent release of Perl, you can +just use the Symbol::delete_package() function instead. + +=head2 How can I use a variable as a variable name? + +Beginners often think they want to have a variable contain the name +of a variable. + + $fred = 23; + $varname = "fred"; + ++$$varname; # $fred now 24 + +This works I<sometimes>, but it is a very bad idea for two reasons. + +The first reason is that they I<only work on global variables>. +That means above that if $fred is a lexical variable created with my(), +that the code won't work at all: you'll accidentally access the global +and skip right over the private lexical altogether. Global variables +are bad because they can easily collide accidentally and in general make +for non-scalable and confusing code. + +Symbolic references are forbidden under the C<use strict> pragma. +They are not true references and consequently are not reference counted +or garbage collected. + +The other reason why using a variable to hold the name of another +variable a bad idea is that the question often stems from a lack of +understanding of Perl data structures, particularly hashes. By using +symbolic references, you are just using the package's symbol-table hash +(like C<%main::>) instead of a user-defined hash. The solution is to +use your own hash or a real reference instead. + + $fred = 23; + $varname = "fred"; + $USER_VARS{$varname}++; # not $$varname++ + +There we're using the %USER_VARS hash instead of symbolic references. +Sometimes this comes up in reading strings from the user with variable +references and wanting to expand them to the values of your perl +program's variables. This is also a bad idea because it conflates the +program-addressable namespace and the user-addressable one. Instead of +reading a string and expanding it to the actual contents of your program's +own variables: + + $str = 'this has a $fred and $barney in it'; + $str =~ s/(\$\w+)/$1/eeg; # need double eval + +Instead, it would be better to keep a hash around like %USER_VARS and have +variable references actually refer to entries in that hash: + + $str =~ s/\$(\w+)/$USER_VARS{$1}/g; # no /e here at all + +That's faster, cleaner, and safer than the previous approach. Of course, +you don't need to use a dollar sign. You could use your own scheme to +make it less confusing, like bracketed percent symbols, etc. + + $str = 'this has a %fred% and %barney% in it'; + $str =~ s/%(\w+)%/$USER_VARS{$1}/g; # no /e here at all + +Another reason that folks sometimes think they want a variable to contain +the name of a variable is because they don't know how to build proper +data structures using hashes. For example, let's say they wanted two +hashes in their program: %fred and %barney, and to use another scalar +variable to refer to those by name. + + $name = "fred"; + $$name{WIFE} = "wilma"; # set %fred + + $name = "barney"; + $$name{WIFE} = "betty"; # set %barney + +This is still a symbolic reference, and is still saddled with the +problems enumerated above. It would be far better to write: + + $folks{"fred"}{WIFE} = "wilma"; + $folks{"barney"}{WIFE} = "betty"; + +And just use a multilevel hash to start with. + +The only times that you absolutely I<must> use symbolic references are +when you really must refer to the symbol table. This may be because it's +something that can't take a real reference to, such as a format name. +Doing so may also be important for method calls, since these always go +through the symbol table for resolution. + +In those cases, you would turn off C<strict 'refs'> temporarily so you +can play around with the symbol table. For example: + + @colors = qw(red blue green yellow orange purple violet); + for my $name (@colors) { + no strict 'refs'; # renege for the block + *$name = sub { "<FONT COLOR='$name'>@_</FONT>" }; + } + +All those functions (red(), blue(), green(), etc.) appear to be separate, +but the real code in the closure actually was compiled only once. + +So, sometimes you might want to use symbolic references to directly +manipulate the symbol table. This doesn't matter for formats, handles, and +subroutines, because they are always global -- you can't use my() on them. +But for scalars, arrays, and hashes -- and usually for subroutines -- +you probably want to use hard references only. + =head1 AUTHOR AND COPYRIGHT -Copyright (c) 1997, 1998 Tom Christiansen and Nathan Torkington. +Copyright (c) 1997-1999 Tom Christiansen and Nathan Torkington. All rights reserved. When included as part of the Standard Version of Perl, or as part of |