X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlfaq7.pod;h=2218c126852e38c99cc925cad30c2612c5112c98;hb=ab4f32c297ca404165732c897d45e499965c42dc;hp=908fc14e7cb3f3b400d9364b2aace0c594cfcc94;hpb=46fc3d4c69a0adf236bfcba70daee7fd597cf30d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlfaq7.pod b/pod/perlfaq7.pod index 908fc14..2218c12 100644 --- a/pod/perlfaq7.pod +++ b/pod/perlfaq7.pod @@ -1,6 +1,6 @@ =head1 NAME -perlfaq7 - Perl Language Issues ($Revision: 1.16 $, $Date: 1997/03/19 17:25:23 $) +perlfaq7 - Perl Language Issues ($Revision: 1.21 $, $Date: 1998/06/22 15:20:07 $) =head1 DESCRIPTION @@ -9,9 +9,14 @@ clearly fit into any of the other sections. =head2 Can I get a BNF/yacc/RE for the Perl language? -No, 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." +There is no BNF, but you can paw your way through the yacc grammar in +perly.y in the source distribution if you're particularly brave. The +grammar relies on very smart tokenizing code, so be prepared to +venture into toke.c as well. + +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? @@ -133,6 +138,12 @@ binds more tightly even than unary minus, making C<-2**2> product a negative not a positive four. It is also right-associating, meaning that C<2**3**2> is two raised to the ninth power, not eight squared. +Although it has the same precedence as in C, Perl's C operator +produces an lvalue. This assigns $x to either $a or $b, depending +on the trueness of $maybe: + + ($maybe ? $a : $b) = $x; + =head2 How do I declare/create a structure? In general, you don't "declare" a structure. Just use a (probably @@ -169,7 +180,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.16 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r}; + $VERSION = do{my@r=q$Revision: 1.21 $=~/\d+/g;sprintf '%d.'.'%02d'x$#r,@r}; @ISA = qw(Exporter); @EXPORT = qw(&func1 &func2 &func3); @@ -262,7 +273,7 @@ Here's a classic function-generating function: } $add_sub = add_function_generator(); - $sum = &$add_sub(4,5); # $sum is 9 now. + $sum = $add_sub->(4,5); # $sum is 9 now. The closure works as a I with some customization slots left out to be filled later. The anonymous subroutine returned @@ -344,16 +355,37 @@ reference to an existing or anonymous variable or function: =item Passing Filehandles -To create filehandles you can pass to subroutines, you can use C<*FH> -or C<\*FH> notation ("typeglobs" - see L for more information), -or create filehandles dynamically using the old FileHandle or the new -IO::File modules, both part of the standard Perl distribution. +To pass filehandles to subroutines, use the C<*FH> or C<\*FH> notations. +These are "typeglobs" - see L +and especially L for more information. + +Here's an excerpt: + +If you're passing around filehandles, you could usually just use the bare +typeglob, like *STDOUT, but typeglobs references would be better because +they'll still work properly under C. For example: + + splutter(\*STDOUT); + sub splutter { + my $fh = shift; + print $fh "her um well a hmmm\n"; + } + + $rec = get_rec(\*STDIN); + sub get_rec { + my $fh = shift; + return scalar <$fh>; + } + +If you're planning on generating new filehandles, you could do this: - use Fcntl; - use IO::File; - my $fh = new IO::File $filename, O_WRONLY|O_APPEND; - or die "Can't append to $filename: $!"; - func($fh); + sub openit { + my $name = shift; + local *FH; + return open (FH, $path) ? *FH : undef; + } + $fh = openit('< /etc/motd'); + print <$fh>; =item Passing Regexps @@ -400,7 +432,7 @@ To pass an object method into a subroutine, you can do this: } } -or you can use a closure to bundle up the object and its method call +Or you can use a closure to bundle up the object and its method call and arguments: my $whatnot = sub { $some_obj->obfuscate(@args) }; @@ -452,6 +484,8 @@ 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 for details. + =head2 What's the difference between dynamic and lexical (static) scoping? Between local() and my()? C saves away the old value of the global variable C<$x>, @@ -495,7 +529,8 @@ In summary, local() doesn't make what you think of as private, local variables. It gives a global variable a temporary value. my() is what you're looking for if you want private variables. -See also L, which explains this all in more detail. +See L and L for excruciating details. =head2 How can I access a dynamic variable while a similarly named lexical is in scope? @@ -528,16 +563,16 @@ 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 "local($foo) = ;" work right? +=head2 Why doesn't "my($foo) = ;" work right? -C gives list context to the right hand side of C<=>. The -EFHE read operation, like so many of Perl's functions and -operators, can tell which context it was called in and behaves -appropriately. In general, the scalar() function can help. This -function does nothing to the data itself (contrary to popular myth) -but rather tells its argument to behave in whatever its scalar fashion -is. If that function doesn't have a defined scalar behavior, this of -course doesn't help you (such as with sort()). +C and C give list context to the right hand side +of C<=>. The EFHE read operation, like so many of Perl's +functions and operators, can tell which context it was called in and +behaves appropriately. In general, the scalar() function can help. +This function does nothing to the data itself (contrary to popular myth) +but rather tells its argument to behave in whatever its scalar fashion is. +If that function doesn't have a defined scalar behavior, this of course +doesn't help you (such as with sort()). To enforce scalar context in this particular case, however, you need merely omit the parentheses: @@ -576,7 +611,7 @@ the function doesn't get an empty @_, it gets yours! While not strictly speaking a bug (it's documented that way in L), it would be hard to consider this a feature in most cases. -When you call your function as C<&foo()>, then you do get a new @_, +When you call your function as C<&foo()>, then you I get a new @_, but prototyping is still circumvented. Normally, you want to call a function using C. You may only @@ -595,12 +630,21 @@ regexp 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. -Here's a simple example of a switch based on pattern matching. We'll -do a multi-way conditional based on the type of reference stored in -$whatchamacallit: +The general answer is to write a construct like this: + + for ($variable_to_test) { + if (/pat1/) { } # do something + elsif (/pat2/) { } # do something else + elsif (/pat3/) { } # do something else + else { } # default + } - SWITCH: - for (ref $whatchamacallit) { +Here's a simple example of a switch based on pattern matching, this +time lined up in a way to make it look more like a switch statement. +We'll do a multi-way conditional based on the type of reference stored +in $whatchamacallit: + + SWITCH: for (ref $whatchamacallit) { /^$/ && die "not a reference"; @@ -630,6 +674,41 @@ $whatchamacallit: } +See C for many other +examples in this style. + +Sometimes you should change the positions of the constant and the variable. +For example, let's say you wanted to test which of many answers you were +given, but in a case-insensitive way that also allows abbreviations. +You can use the following technique if the strings all start with +different characters, or if you want to arrange the matches so that +one takes precedence over another, as C<"SEND"> has precedence over +C<"STOP"> here: + + chomp($answer = <>); + if ("SEND" =~ /^\Q$answer/i) { print "Action is send\n" } + elsif ("STOP" =~ /^\Q$answer/i) { print "Action is stop\n" } + elsif ("ABORT" =~ /^\Q$answer/i) { print "Action is abort\n" } + elsif ("LIST" =~ /^\Q$answer/i) { print "Action is list\n" } + elsif ("EDIT" =~ /^\Q$answer/i) { print "Action is edit\n" } + +A totally different approach is to create a hash of function references. + + my %commands = ( + "happy" => \&joy, + "sad", => \&sullen, + "done" => sub { die "See ya!" }, + "mad" => \&angry, + ); + + print "How are you? "; + chomp($string = ); + if ($commands{$string}) { + $commands{$string}->(); + } else { + print "No such command: $string\n"; + } + =head2 How can I catch accesses to undefined variables/functions/methods? The AUTOLOAD method, discussed in L and @@ -642,7 +721,7 @@ C<__WARN__> like this: $SIG{__WARN__} = sub { - for ( $_[0] ) { + for ( $_[0] ) { # voici un switch statement /Use of uninitialized value/ && do { # promote warning to a fatal @@ -669,15 +748,18 @@ before Perl has seen that such a package exists. It's wisest to make sure your packages are all defined before you start using them, which will be taken care of if you use the C statement instead of C. If not, make sure to use arrow notation (eg, -Cfind("Samy")>) instead. Object notation is explained in +Cfind("Samy")>) instead. Object notation is explained in L. +Make sure to read about creating modules in L and +the perils of indirect objects in L. + =head2 How can I find out my current package? If you're just a random program, you can do this to find out what the currently compiled package is: - my $packname = ref bless []; + my $packname = __PACKAGE__; But if you're a method and you want to print an error message that includes the kind of object you were called on (which is @@ -709,7 +791,26 @@ Use embedded POD to discard it: =end comment text + =cut + +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. + =head1 AUTHOR AND COPYRIGHT -Copyright (c) 1997 Tom Christiansen and Nathan Torkington. -All rights reserved. See L for distribution information. +Copyright (c) 1997, 1998 Tom Christiansen and Nathan Torkington. +All rights reserved. + +When included as part of the Standard Version of Perl, or as part of +its complete documentation whether printed or otherwise, this work +may be distributed only under the terms of Perl's Artistic License. +Any distribution of this file or derivatives thereof I +of that package require that special arrangements be made with +copyright holder. + +Irrespective of its distribution, all code examples in this file +are hereby placed into the public domain. You are permitted and +encouraged to use this code in your own programs for fun +or for profit as you see fit. A simple comment in the code giving +credit would be courteous but is not required.