Programming Perl, 3rd Edition by Larry Wall, Tom Christiansen and Jon Orwant Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. This page was updated April 1, 2008. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: ?Preface? Some of the code examples in the book don't work with versions below 5.6. But some programmers still work with earlier versions, e.g., in companies where they have to "work with what you get". Except on the back cover I couldn't find any note in the book that this book covers 5.6 and that the code examples are based on that version. On page xxxii would be a place and space for a short note. [xxv] 2nd and 3rd para under Searching Man Pages; The proceedure shows on this page for search the perl documentation files do not work any where I have accesss to a perl installation, including `This is perl, v5.6.0 built for i386-linux' In particular the syntax shows: perlop comma perlfunc split perlvar ARGV [...] And the text says it is possible to search those docs for the following string by typing the above commands at a prompt. perlhelp CORE::GLOBAL Is given as an example of searching the entire documentation. None of those techniques or commands work on 7 differnet perl installs I tried. Several were recent 5.6.0 versions (4) 2nd paragraph, 1st line; "rational" is hyphenated at the end of the line as "ratio-nal" instead of "ration-al" (25) 4th paragraph; "You can do this with almost any binary operator" (which appears after the line that begins, "which reads 'multiply $a by 3'.") should be the start of a new paragraph. ?33? footnote, 2nd-to-last line: Is "That's just inefficient" correct? What does "That" refer to? Maybe the 3rd sentence of the footnote ("Despite ...") had been inserted at a later moment and the connection got lost/confused? {37} end of page; "For example, /a./ will match any string containing an "a" that is not the last character in the string." -- The regexp /a./ will match any character containing an a followed by another character, so 'aa' will match. Here 'a' IS the last character in the string. {41} 4th paragraph, 1st line; It would be clearer to say "(between the second and third forward slashes)" rather than just "(between the second and third slashes)" since there is a plethora of both forward and back slashes in the example line of code. (41) 4rd paragraph; The paragraph reads "The right side of the substitution is ... which is why you can interpolate variables there, including backreference variables." However, the book does not include any previous definition of what neither variable interpolation or interpolation is. Are they referring to interpolation as synonym of "swapping" and "substitution" maybe?. Are they referring maybe to "string interpolation", as seen in some Python examples?. The same paragraph continues stating "This is a powerful concept: interpolation ... is one of the reasons Perl is a good text-processing language." and "interpolation is good for putting things back together again." I believe the autors should include a formal definition of interpolation and variable interpolation before they refer to it. I think that addition will avoid misunderstandings. {42} Roughly sixth paragrath; No glossary entry for "opcodes" in sentence "So the compiler generates internal opcodes that reflect this." {49} third paragraph, last sentence: "Statements in Perl are terminated with semicolons..." seems to be slightly inaccurate, as it seems (from experimentation) that the statements in Perl are separated with semicolons. If this is true, perhaps a footnote is in order. (The statement about C is true.) {50} first paragraph, first line: "...if a line begins with = anywhere a statement would be legal..." It seems that an alphabetic character must immediately follow the =. Otherwise, Perl responds with a syntax error. {53} 3rd paragraph (also page 23, paragraph 2 from bottom); The description of evaluating filehandle in angle brackets in while loops conditional seems a bit incomplete and misleading to me. I am using version 5.005_03 of perl for tests; The code lines on page 53 explaining that while () is a shortcut to while (defined($_ = )) are consistent with my tests; but not with explanations on pages 53 and 23, which claim that $_ is checked using Perl criteria for truth; The explanation from the book can be proven wrong in one case: when last line of data consists of character '0' with no trailing space: Please compare results of the following tests: perl -e 'print "0";' | perl -e ' while () { print; print "=TRUE=" if $_; print "=EOL=\n" }' and perl -e 'print "0\n";' | perl -e ' while () { print; print "=TRUE=" if $_; print "=EOL=\n" }' which show that line containing '0' alone is processed, even though it evaluates to false. (54) Last sentence of 1st paragraph; Put "(" in front of "Don't blame us.)" {54} 1.-2: There are two closing parantheses (line -2 and line -1). I suggested you delete the first one. {60, 748} On page 60 "With the oct function ---which works for hex and binary numbers, too, as it happens, provided you supply the 0x or 0b on the front" On page 748 "If EXPR happens to start with "0x", it is interpreted as a hexadecimal" "If EXPR happens to start with "0b", it is interpreted as a binary" Omit the "0" seawolf:ndbr perl -e 'print oct 377,"\n"' 255 seawolf:ndbr perl -e 'print oct xff,"\n"' 255 seawolf:ndbr perl -e 'print oct b111_1111,"\n"' You see the correct result without leading "0"; Garbage if you add leading "0": ndbr_nesac2: perl -e 'print oct 0377,"\n"' 173 ndbr_nesac2: perl -e 'print oct 0xff,"\n"' 173 ndbr_nesac2: perl -e 'print oct 0b1111_1111,"\n"' Bare word found where operator expected at -e line 1, near "0b1111_1111" (Missing operator before b1111_1111?) syntax error at -e line 1, near "0b1111_1111" Execution of -e aborted due to compilation errors. {61} first table; The following backslashed escape sequences are missing from the table: \$ Dollar sign \@ At sign \\ Backslash [63] 4th paragraph (counting the first incomplete paragraph); Regarding quoting constructs, the book states on the 4th paragraph of page 63, "If you choose single quotes for delimiters, no variable interpolation is done even on those forms that ordinarily interpolate." This is false. Several of the constructs interpolate no matter what. 'q' and 'qq' in particular never interpolate. In other words, even if you choose a single quote for the quote delimiter it will continue to interpolate. The correct interpretation is contained in 'perldoc perlop' in the 'quote and quote- like operators'. [63] Pick Your Own Quotes; The sentence "In table 2-3, any nonalphanumeric, nonwhitespace delimiter may be used in place of /." is not true, at least for the "qr//" form of quote under ActiveState Perl v 5.6.1. The $np pattern listed on pg. 214 fails to compile for these delimiters (and perhaps others) # <> | ^ - _ Using parentheses causes Perl to crash due to an error in PERL56.DLL [66] next to last and previous code fragment; The two "Hurrah" examples fail to compile under Perl 5.6.1 . The error message is "Can't find string terminator "" anywhere before EOF at ... " (77) 1st full paragraph; This paragraph says that using the "=>" operator is "convenient for several sorts of operation, including initializing hash variables". Unless the word "operation" is one of those special words like "fish" that doesn't acquire an "s" when made plural, I am led to believe that this is a typo. I think that "operation" could stay without the "s" if the word "sorts" were changed to "modes", but this change may not fit the context properly. {80} 5.-1: Replace semicolon at end of paragraph (by : or .). (82) 5.1 (comment): "iff" -> "if" [100] first paragraph: "File ages ... since the script started running ..." is incorrect. It should read "File ages ... prior to when the script started running." Also, the subsequent "This time ..." should be "The time when the script started running ...", or the text should be reorganized. In this context, "This" is, at the very least, ambiguous. {103} paragraph just before the "Range Operator" section header; Table 1-1 should be Table 3-1 [104] 1st code example section, line 3; s/^/> / if (/^$/ .. eof()); # quote body of a message should be corrected as: s/^/> / if ((/^$/ .. eof()) > 1); # quote body of a message Reason: The first matching line is the empty line, which is not thought to be a part of the message body. We've got to skip this line as the above correct code does so that it will not mislead users and harm the message structure, if they cut and paste it. :-) {106} 3rd code example: missing ; after printf {117} 1st full paragraph: The variable "bit" should be initialized to 1 as it is in the next paragraph. (117) line 9: Reviewer says, this examples only works when $bit = 1 {119} Final paragraph/code example; " Here's how a C or Java programmer might first think to code up a particular algorithm in Perl: for ($i = 0; $i < @ary1; $i++) { for ($j = 0; $j < @ary2; $j++) { if ($ary1[$i] > $ary2[$j]) { last; # Can't go to outer loop. :-( } $ary1[$i] += $ary2[$j]; } # this is where that last takes me } " This ("Can't go to outer loop" comment, especially) implies that Java does not have the ability to label a for loop, which is not true. Java example: WID: for (int i = 0; i < ary1.length; i++) { JET: for (int j = 0; j < ary2.length; j++) { if (ary1[i] > ary2[j]) { continue WID; # Can go to outer loop :-) } ary1[i] += ary2[j]; } } [119] example at bottom of page; C or Java programmers use "break", not "last" {123} 2nd code fragment (immediately before heading "Bare Blocks"); On line 1 of the code sample, FILE is a filehandle. On line 3 of the example, FILE is a label. This is misleading for three reasons: 1. One looks for (and doesn't find) a line labeled "FILE:" 2. Two things as disparate as a filehandle and a label should not have the same name. 3. The reuse of the name FILE leads to the false impressions that the code fragment is self-contained and that the "next" operator can take a filehandle as an argument. {124} 1.3: Reviewer has doubts about "if $x = $y ** 2" (also in the next two codes). Is this correct? Shouldn't that be "if $x == $y ** 2"? (126) "It cant be used to jump into any construct" "can't" is missing an apostrophe. [131] 1st paragraph: "When you assign to a modified lvalue, the modifier doesn't change whether the lvalue is viewed as a scalar or a list. To figure how the assignment will work, just pretend the modifier isn't there. So either of: >> my ($foo) = ; my @array = ; supplies a list context to the righthand side"... The line I've flagged with ">>" should read my (@foo) = ;. ^ {138} -4: Shouldn't "no strict 'vars'" read "no strict 'vars';" (semicolon added)? (139ff) Chapter 5: inconsistent definition of vowels ([aeiou] and [aeiouy]) within this chapter [140] 3rd paragraph under The Regular Expression Bestiary "Other characters don't match themselves, but "misbehave" in some way. We call these metacharacters. (All metacharacters are naughty in their own right, but some are so bad that they also cause other nearby characters to misbehave as well.) Here are the miscreants: \ | ( ) [ { ^ $ * + ? . closing square bracket ']' and closing brace '}' are not included in metacharacter list. {142} 4.2: section "Capturing and Clustering" doesn't follow after "Alternation" but appears before it (see pages 182 and 187) (143) 2nd paragraph, 7th sentence; This sentence describes circumstances in which the regular expression metacharacter, dollar sign ($), can take on different meanings depending on context. However, what's written does not accurately define this example. The following text: '...any $ immediately followed by a vertical bar, closing parenthesis, or the end of the string will be treated not as variable interpolation, but as the traditional regex assertion meaning end-of-line.' should be something like: '...any $ immediately following a vertical bar, closing parenthesis, or the end of the string will be treated not as variable interpolation, but as the traditional regex assertion meaning end-of-line.' (144) 6th paragraph; 'See "Variable Interpolation"' should read See "Variable Interpolation" later in this chapter just as it does at a later point in the chapter {149} 2.4: "stolen right out the Perl Cookbook": The recipe there (6.16) differs a bit from the code used here. {158} after 2nd paragraph; The right bracket character is not generally considered to be a metacharacter. The list of the Dirty Dozen RE metacharacters does not include it, nor does any of the following material that I have searched (including the section on Character Classes) mention any special characteristics for it. However, ']' cannot be used in a character class without being escaped. I'd like to see this mentioned in the section on Character Classes, including the specific information on how ( '\]') to escape it. I'm a bit spoiled by the Camel; I seldom have to guess about this sort of thing. Let's keep it that way... (165) Bottom paragraph; In the third sentence, either remove the word "a" or replace the first occurrence of "classes" with "class" (166) 3.-5: "idiograph" -> "ideograph" (Or is this Yet Another Linguistic Sugar?) {166} first and third paragraphs; For example, [aeiouy] matches [any lower case] letter that can be a vowel. For example, [^aeiouy] matches any character that isn't a [lower case] vowel. (172) 1st paragraph: Shouldn't "you wonder whether it were written in Greek script" read "you wonder whether it was written in Greek script"? (176) 3.3: "verions" -> "versions" {181} To get the example to work, I had to add "g" to 3 lines as listed below: last half of example at bottom of page: $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; # Add g after last / here $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; # and here $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; # and here. {181-182} \G Assertion program: In the second section of code, the comments line states that $1 equals "deg", then "ml", then "oz". But when you run the program, you get "Preheat" every time. Also, the output for the prgram gives the correct numbers (in the order they come in the paragraph), but it only says "deg of fahrentheit" over and over rather than "deg of fahrenheit, ml of dilitium" etc. The corrected code is as follows: #!/usr/bin/perl #The \G Assertion: Corrected Code ($recipe = << 'DISH') =~ s/^\s+//gm; Preheat over to 451 deg. fahrenheit. Mix 1 ml. dilithium with 3 oz. of NaCL and stir in 4 anchovies. Glaze with 1 g. mercury. Heat for 4 hours and let cool for 3 seconds. Serves 10 aliens. DISH $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; #$1 is now "deg" $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; #$1 is now "ml" $recipe =~ /\d+ /g; $recipe =~ /\G(\w+)/g; #$1 is now "oz" pos($recipe) = 0; while ($recipe =~ /(\d+) /g) { my $amount = $1; # On below line: Took off + from \s+ and added cg if ($recipe =~ / \G (\w{0,3}) \. \s (\w+) /cgx) { print "$amount $1 of $2\n"; } else { $recipe =~ / \G (\w+) /cgx; #Added cg print "$amount $1\n"; } } {190} first code sample; The code sample shows how to skip comments and blank lines while reading files. It has two next if statements: next if /^#/; next if /^\s*(#|$)/; But unless I'm missing something, the second regex matches what the first one does, so the first one is unnecessary. I prefer using this: s/#.*//; # toss comments to EOL next if /^\s*$/; # skip (now) blank lines which also catches trailing shell/Perl-style comments like those in my code sample itself. [208] The cvmap program in the middle of the page; I follow the example and run it.. but it doesn't work. The Third "FOR" loop did nothing {208} cvmap program; The program requires that the word that is input be in all lowercase. (209) "milquetoasts" has an extra s. [214] top; the example shows the use of a recursive regular expression (i.e., a regular expression that refers to itself via the (??{ ...}) embedding sequence). the text before the example says "The following pattern matches a set of nested parentheses, however deep they go:". in fact, in perl 5.6.1, this seems to not be the case. the expression will only match parentheses nested to a depth of two. nesting of depth 3 or higher will cause the pattern to fail. for example, "()" and "(())" match, but "((()))" (which is clearly a balanced expression) does not match. {226} The description of prototypes in chapter 6 is missing an important hint. Insert the following sentence before the last sentence on the page: "The value passed as part of `@_' will be a reference to the actual argument given in the subroutine call, obtained by applying `\' to that argument." (I took this description from the perlsub(1) manpage for perl v5.6.0.) Later chapters, for example chapter 8, page 244, third paragraph refer to this behaviour so it is important to have this line added. {232} 4th paragraph (just after the "The lvalue attribute" heading): The example to show how to return a modifiable scalar value from a subroutine uses a variable called $val. However, when calling the "canmod" subroutine, a variable called $x is used, which causes the program, if copied onto an editor and executed, to generate a different result. The variable $x should be changed to $val. [234]And a correction to the actual book, on page 234". The code sample for declaring formats is missing a period. The text in the book reads >Output record formats are declared as follows: > > format NAME = > FORMLIST It should read >Output record formats are declared as follows: > > format NAME = > FORMLIST > . [239] On page 239, the code sample showing how to eval a format will print one more column than the value in $cols (because the '^' takes up one space in the output). The unwary reader would expect $cols to represent the number of columns in the output, not one less than the number of columns, and the code should probably contain "($cols - 1)" instead of "$cols". Correspondingly, two lines later should probably refer to "($cols - 9)" instead of "($cols -8)". Also in that same code sample, the \t should really be replaced with " " x 8, rather than relying on an 8-column tab-stop, and the sample output immediately following on that page is a perfect example of the reason for this, since your tab setting appears to have been set to 4 rather than 8. [240] On page 240, in section "Accessing Formatting Internals", the first code example assigns the result of the formline function call to the variable $str. This is nonsensical. According to chapter 29, formline always returns true, and "perldoc -f formline" says nothing about its return value. Testing the code, chapter 29 appears to be true. The "$str = " should be removed from the code example. (243) 3.4: Not a bug, just an idea from techreviewers: According to the pair employer/employee "referee" could be used instead of "referent". (By the way, one possible German translation of "referee" is "Referent" ...) {243&246} diagrams 8-1 and 8-2; In diagram 8-1, you make a distinction with the destination of an arrow for hard and symbolic references. For hard references, the destination of the arrow is the value. For symbolic references, the destination of the arrow is the name. In diagram 8-2, you are displaying the encoding of the previous $arrayref = [1, 2, ['a', 'b', 'c', 'd']], which are, as I understand it, hard references. Yet the destination of the arrows are the (empty) name area of the value, not the value. This seems to me to be an inconsistency. (244) 1st paragraph: The sentence: A hard reference doesn't know something's name just to refer to it,... doesn't make sense (to me) as stated. Should it be something like: A hard reference doesn't need to know something's name just to refer to it, or: A hard reference doesn't know something's name, just to refer to it, (Note additional comma.) I'm not sure which meaning was intended. (244) Chapter on references; A reference can point to any data structure. Since references are scalars, you can store them in arrays and hashes, and thus build arrays of arrays, arrays of hashes, hashes of arrays, arrays of hashes and functions, and so on. There are examples of these in Chapter 9. ^^^^^^^^ The above paragraph lists "arrays of hashes" twice. I assume that the second listing of "arrays of hashes" was intended to read as "hashes of hashes". (247) penultimate example: I'm not sure whether an observant Jew would be offended by the use of the word "hashem," but it still seems ill-advised. (250) Footnote; ...so you shouldn't rely on the typeglobbedess of what open... Should it be "typeglobbedNess" instead of "typeglobbedess"? (249) -1.1: "use use" -> "use" [254] last paragraph: I was confused as to how to obtain the "C behavior" that is discussed following the two examples given for accessing elements in a 2-dimensional array. I set up a 2D array like this: @myarray = ( [1,2,3,4], [5,6,7,8], [9,10,11,12] ); and a reference like this: $listref = \@myarray; These worked: $listref->[2][2] = "hello"; $$listref[2][2] = "hello"; The paragraph suggests ${$listref[2]} to obtain C behavior, but I couldn't see how to make that apply to this particular data structure, since it only appears to refer to one dimension. The alternative $listref[2]->[$greeting] = "hello"; makes more sense on paper, assuming $greeting exists or no declaration is required, but it did not alter my array in practice. The array was unaltered, and I seemed to be autovivifying something. Did the paragraph mean to imply that these were equivalent to the first two access methods, on the same data structure--or was I reading too much into the "equivalence" that was being discussed? [254] last paragraph; Prompted by a question on the beginners' list: The Camel, ( 3rd Ed. ), says, ----------------------------------------------------------------$listref->[2 ][2] = "hello"; # pretty clear $$listref[2][2] = "hello"; # A bit confusing This second of these statements may disconcert the C programmer, who is accustomed to using *a[i] to mean "what's pointed to by the ith element of a". But in Perl, the five characters ($ @ * % &) effectively bind more tightly than braces or brackets. Therefore, it is $$listref and not $listref[2] that is taken to be a reference to an array. ----------------------------------------------------------------- This example is not in perlref, although it was in the Camel 2nd ed, so it is with some trepidation that I question the accuracy of the last sentence. $$listref is not a reference to an array, it's an error: $ perl -Mstrict -wle 'my $listref = [3, 5, [9, 11, 13]]; print $$listref' Not a SCALAR reference at -e line 1. It seems to me that it would make more sense if it read Therefore, it is $listref and not $listref[2] that is taken to be a reference to an array. since it's trying to make the point that $$listref[2][2] is ${$listref}[2][2] and not ${$listref[2]}[2]. [256] 2nd line of 3rd code example: key-value confusion: "brown" within qw() should read "weight". (257) 5.2: A comma is missing after "@a". ?257? -4.1: Not a bug, just a comment: Our techreviewer considered the comment "But only single aggregates expand" as hardly understandable. (258) 3rd code example: July 16, 2000 was a Sunday. (I only bothered to check in order to practice the Doomsday algorithm.) {262} topmost example; You probably didn't intend to include the semi-colon in the 4th line of the 5-line example. [271] 3rd paragraph of section "Access and Printing"; The paragraph says: "Perl never automatically dereferences for you." But this is contradicted on page 295, 6th paragraph: "... because Perl automatically dereferences the typeglob reference for you." FYI: A similar sentence exists in "perldoc perllol": "because you'll get just references listed, and perl will never automatically dereference things for you." {281} 2nd code example; The definition of the "new folks" hash looks like this: %new_folks = ( wife => "wilma", pet => "dino"; ); The semicolon after "dino" is a syntax error. I verified that the perl compiler chokes on this error. A comparison with other code examples in Chapter 9 suggests that the author intended a comma rather than a semicolon. (I'm using perl version 5.6.0 on sun4-solaris and version 5.6.1 on i686-linux.) {284} %TV hash; The "series" keys and accompanying values are redundant, as the values ("flintstones", "jetsons", and "simpsons') are already the keys of the %TV hash. (285) 2.2 (2nd line below heading): "data declarations" -> "data definitions" (tech reviewer pointed to Kerninghan & Ritchie for the difference between declaration and definition) (291) 4.5-6: The symbol table is stored in the symbol table? Shouldn't that read, "the reference to the symbol table ..."? [292] Paragraph 4 and 5, on eval and __PACKAGE__ ; >package Foo; > >print eval "__PACKAGE__"; Gives me output: < main not < Foo as I would have expected after reading those paragraphs. Tested with Active State Perl 5.6.1 and 5.8.0 and 5.6.1 under Linux {295} 1st paragraph; Last sentence reads "Note that both techniques only work with package variables; they would not have worked had we declared %units with my." This is false, the example code runs just fine with %units declared as a lexical variable (v 5.6.1, linux) {300} about 3/4 of the way down the page; You used (forward) slashes as the pathname component separator for a Windows file. I think you meant to use backslashes. (310) 1.-2: "Closures as Objects"--there is no such section in this chapter. Do you mean the section "Using Closures for Private Objects"? [318] Chapter 12, last paragraph: the package name (passed in as the first argument) to bless: should be: the package name (passed in as the second argument) to bless: (333) near end of third paragraph: The next-to-last sentence of the third paragraph on page 333 says: "...including the standard Struct::Class module..." There is no Struct::Class module. This should be changed to "Class::Struct" module. {333} -3.2 (and following pages): Although you are talking about Tolkien's races, the use of "race" for the "Person" class could be misunderstandable as an agreement that it would be okay to sort, classify (or so ...) people by their race. (When we translated these examples into German --race = Rasse--we felt that they would read pretty insensitive.) [336] 2 examples under "Generating Classes with Class::Struct"; Problem: values assigned to the 'aliases' instance variable (in the second example) get lost. Reason: apparently Class::Struct does not allow direct assignment of an array ref using the accessor method of an element of type '@'. Possible Workarounds: - make aliases a '$' element type in Person (in the first example) - OR do assignments in the second example in the way required by Class::Struct for '@' type elements, i.e.: $mage->aliases(0, "Mithrandir"); $mage->aliases(1, "Olorin"); $mage->aliases(2, "Incanus"); - OR do the assignment in the constructor (which does seem to take array refs), e.g.: my $mage = Person->new(name=>'Gandalf', race=>'Istar', aliases=>["Mithrandir", "Olorin", "Incanus"]); [338] 1st paragraph, 1st code example: code example reads: sub AUTOLOAD { my $self = shift; # only handle instance methods, not class methods croak "$self not an object" unless ref($invocant); my $name = our $AUTOLOAD; ... ... It should read: sub AUTOLOAD { my $self = shift; # only handle instance methods, not class methods croak "$self not an object" unless ref($self); my $name = our $AUTOLOAD; ... ... $invocant isnt defined in this routine or in the package for which the routine is being defined. (343) last item in list: "the value one of its attributes" -> "the value of one of its attributes" ^^ {347} top; There is nothing in the chapter on Overloading to indicate that there is a general restriction on the context in which overload functions are called. Overloaded '+', for example, is always called in scalar context, even though the function that implements it works properly in array context. I am assuming that this is a design decision (though a bad one, IMO), rather than a bug in Perl, so I am reporting it as a documentation oversight. Of course, if it's really a Perl bug, then I'm happier, because then there's a chance it will be fixed. ?349? footnote, line 3: What is meant by "additive"? Did you mean "associative"? (363) 2.2-3: "archetypal behavior" or "archetypic behavior"? {369} -1.-1: dot instead of comma after ">" 9) sub FETCH; A compiler error is generated because the $fh following "my" does not have parenthesis. sub FETCH { my $self = shift; confess "I am not a class method" unless ref $self; return unless open my $fh, $$self; read($fh, my $value, -s $fh); # NB: don't use -s on pipes! return $value; } should be return unless open my ($fh), $$self; {371} 1st code example; I think # Prints: # 100 Red # 101 Green # 102 Blue should be # Prints: # 101 Red # 102 Green # 103 Blue This is the result I got when running the example under Perl 5.8.0. (375) -2.2: "can can" -> "can" (379) example code at the top of the page: The STORE method is missing a $ on the hash key. Change: push @{$self->{key}}, $value; to: push @{$self->{$key}}, $value; [384] sub READLINE { ...} code example; The sample code for sub READLINE fails to return the entire array of lines when the tied file handle is used in an array context. Instead, the implementation should look something like this: sub READLINE { my $self = shift; if (wantarray()) { my @tmp = @$self; @$self = (); return @tmp; } else { return pop @$self; } } (385) First code paragraph; In the 2nd and 3rd line of the page 385: The quick brown fox jumps over over the lazy dog %d times! The word 'over' is repeated in a way that suggest an oversight instead of an intent. It should probably be removed from one of the two lines. {385} Last line; Although the text read, "...the my $self furnishes an undefined scalar to open, which knows to autovivify it into a typeglob.", this does not work for me in practice. When I run the code, as printed and unaltered, from the book, the program fails with the error: "Can't use an undefined value as filehandle reference at Shout.pm line 10." I am using the ActiveState build 623 release of Perl v5.6.0 for Win32 systems. (385) sub TIEHANDLE, line 4; open my $self, $form, @_ or croak ... fails at run time in my tests when invoked as a result of executing the example on p. 389 tie(*FOO, Shout::, ">filename"); @_ is empty. I imagine that the 3-argument form of open() is being called with an undefined 3rd argument. open my $self, $form . @_ or croak ... or open my $self, "$form@_" or croak ... executes without complaint. ?386? line 1: Reviewer: It might be a good idea to mention that autovivification of file handles works only with Perl 5.6 and beyond. A hint to use Symbol::gensym might help users of older Perl versions. {389} bottom code sample; The line tie(*FOO, Shout::, ">filename"); should be replaced with tie(*FOO, Shout::, "+>filename"); in order to enable read access, which is assumed by @lines=; further down the listing. Alternatively, the file could be reopened with "; is reached. Also, on p.390 (lines 4 and 5) - further down this same code sample - the word "hello" in the comments on these two lines should be "HELLO" since the uppercased version was printed to the file. {391} 2.10: "$fh" (in comment) should read "$self". (Reviewer wrote: In the function TIEHANDLE in the Shout class, the variable $self is blessed while the comment names is $fh.) {395} code, TIESCALAR sub: Reviewer: The open call in TIESCALAR has a comma where a dot should join ">" and $filename. Fix: The line should read: open(my $handle, ">" . $filename) {396} 1st code: Remove "$x =" in line 4. (Reviewer: The result of the tie is stored in the variable $x. That breaks the example since it is a *second* active reference.) [396] Chapter 14, Example "sub comment {": print { $self->{FH} } $handle $message, "\n"; should be print { $self->{FH} } $message, "\n"; {396} 3rd code: Remove "$handle " in line 4 (print). ?396? last paragraph: Reviewer: In the "Remember" (p 396) example, it should be mentioned that the problem only occurs if the system does not support fflushNULL or fllushall. Older versions of Perl cannot run the example because of the glob autovivification used in the Remember TIESCALAR. [396] topmost example; I think you meant to omit the "$x = " from that example. {413} First paragraph on the page. "Since entries in the %SIG array can be hard" The bold word should be a "hash" not array. [416] code example, middle of page: The while loop should be: while (($zombie = waitpid(-1, WNOHANG)) > 0 ) { $Kid_Status{$zombie} = $?; } i.e., "> 0" and not "!= -1" since waitpid returns 0 if no processes have died yet, and 0 is not a valid process ID. {416} the REAPER sub reads: sub REAPER { 1 until waitpid(-1, WNOHANG) == -1) } It should be: sub REAPER { 1 until ( waitpid(-1, WNOHANG) == -1 ) } #proper () use [417] 4th paragraph - code; The piece of code which is given as an example for File Locking is wrong. Since there are two nested eval() statements, the $@ variable is not propagated back to the outer declaration block. So the die() line is never executed. One way to solve it: eval { ... eval { ... }; alarm 0; die ($@) if ($@); # Propagate $@ }; alarm 0; die if $@ && $@ !~ /alarm clock restart/; # reraise (422) description of "File Locking": The text states: # must get lock before opening database flock(DBLOCK, LOCK_SH) or die "can't LOCK_SH $LCK: $!"; This is an apparent clash with the rest of the example and the surrounding text. The example proceeds to "tie(....O_RDWR | OCREAT)" and the test says "you can do whatever you'd like"; so that all indicates the prior "LOCK_SH" should have been a "LOCK_EX". Also, by the way, in my opinion "DB_LOCK" would be a better name for the file handle, instead of "DBLOCK", which reads as "D BLOCK". [417] Section "Timing Out Slow Errors"; Hi, I have the Camel (3rd Edition, 3rd printing), and on 417 we find: use Fcntl ':flock'; eval { local $SIG{ALRM} = sub { die "alarm clock restart" }; alarm 10; eval { flock(FH, LOCK_EX) or die "can't flock: $!"; }; alarm 0; # cancel the alarm }; alarm 0; #race condition protection --- The issue is: Why are is alarm 0 set after the eval blocks? I would have expected them to be inside the evals... like this: eval { local $SIG{ALRM} = die {...}; alarm 10; eval { # Do something or die "..."; alarm 0; }; alarm 0; }; so that the alarm is stopped before moving into the outer eval, unless we died. If we did die, we stop the alarm ASAP, before proprogating the error (not shown... error in book). If an alarm comes before we stopped it in the outer eval (because the inner die was not for an alarm signal), then we simply die harmlessly in the outer eval... such that we still have caught the exception properly. I can find no evidence of this issue in the Erratas issued. Is this my mistake, or yours? If mine, please point me to the relevent chapters of either the Camel, the Cookbook or the Advanced Perl Programming books. [427] 4th code example; There is a comment indicating that the new form of open is supported starting in 5.6.1. I tried that example (as well as other attempts to use the same form of open) in 5.6.1 and it doesn't work, complaining "Can't use an undefined value as filehandle reference". ?432? 2.3+4: One of our techreviewers considers the two select lines far too sophisticated--and understandable only for about 10% of Perl programmers. Can this be changed to the following lines: my $oldfh = select(TO_CHILD); $| = 1; # autoflush for TO_CHILD select(TO_PARENT); $| = 1; # autoflush for TO_PARENT select($oldfh); {432} The third and fourth lines of the code example; select((select(TO_CHILD), $| = 1))[0]); # autoflush select((select(TO_PARENT), $| = 1))[0]); # autoflush have too many ')'s between '$| = 1' and '[0]);'. ... the lines should be: select((select(TO_CHILD), $| = 1)[0]); # autoflush select((select(TO_PARENT), $| = 1)[0]); # autoflush [434] top (the code sample); The sample code "sleeps" for 1/5th of a second - removing this serious limitation causes both the server and the client programs to fail: "Broken pipe" is the server error, null input is the client error. There is no explanation whatsoever of how to manage high-speed named pipes in the "Named Pipes" section, or (if it cannot be done), we're not told this either. (437) -3.5: "it that all" - correct English? ?440? select((select(Server), $| = 1)[0]); replaced with: my $oldfh = select(Server); $| = 1; # enable command buffering select($oldfh); (440) The comment "# enable command buffering"; Change to "# autoflush" {441} First sample under "Networking Servers"; The sample reads: "use IO::Socket::INET", but it should be: "use IO::Socket"; (442) source code at end of the page: open (STDIN, "<<&Client") or die "can't dup client: $!"; This code always produces the "or die" part when a client connects. The right code is as follows: open (STDIN, "<&Client") or die "can't dup client: $!"; [453] Chapter 17, down the page: $t1->tid() == $td->tid() should be $t1->tid() == $t2->tid() [460] Chapter 17, in the first function of the example: cond_signal($wait_var); $wait_var = 1; cond_wait $wait_var until $wait_var == 2; I think it should be $wait_var = 1; cond_signal($wait_var); cond_wait $wait_var until $wait_var == 2; because the cond_signal() releases the lock on $wait_var. I would also suggest to add the following clarification to the second paragraph: The cond_signal function takes a variable already locked by the current thread, releases the lock, and unblocks one thread that's currently... ?506? Chapter 20: Translator and techreviewer considered this chapter at many places as pretty difficult to understand. Nonexperts would have a hard time with this chapter. {515} 2.2-3 You can add _another expression_ <--> list _them_ <--> delete _them_ (515) -2.-1: "See also" -> "(See also" (opening paran is missing) [521] last paragraph: putting trace information into the file db.out. should be: putting trace information into the file tperl.out. (See the parameter example above the paragraph.) (537) 4.2: The actual section name is a bit different; see page 553. (539) 2.-2 "Perl program" -> "C program" {543} second paragraph: Before reading the "perlcall" manpage, Programming Perl (3rd Ed) readers are referred to the "perlguts" and "perlapi" manpages. However, as far as I can tell, there is no such beast as the "perlapi" manpage. When I read the "perlcall" manpage, it suggests that you read "perlguts" and "perlxs". Both of these exist on my systems. [567] first display: The sample program given to "safely" run subprocesses makes a mistake that, depending on circumstances, may ruin the purpose. You should set GID before UID. It is quite likely that setting gid will otherwise fail because the child lacks authority to change groups at that point. (This is, of course, quite dependant on the OS being used.) ?574? -2.-3: Reviewer: Last sentence in this para ("Although it's better ...) should be revised because of security issues and because of what is said later in the chapter. [575] 2nd Example; SUFFIX = '.dat'); should read: SUFFIX => '.dat'); The published example will not compile. Make the above change, and all works as designed. {576} 1st paragraph: $virtname = "=&" . fileno(TMP); should read: $virtname = "&=" . fileno(TMP); {580} example; I think you meant "-type" to be "content-type". ?583? -1.4: Mention the meaning of "MTBF" (Mean Time Between Failure). {587} Third paragraph from the bottom; "assign the first line to $foo[1]" should be "$foo[0]". {595} Third bullet item; The two instances of "chop" should be "chomp". {597} under the 2nd pin: if ($a) { $foo =3D $a; } elsif ($b) { $foo =3D $b; } elsif ($c) { $foo =3D $c; } should be: if ($a) { $foo =3D $a; } elsif ($b) { $foo =3D $b; } else ($c) { $foo =3D $c; } It makes a difference if $c is "0" or "". [598] last line; I think the sentence: Avoid using eof if return values will already indicate it. should read: Avoid using eof() if return values will already indicate it. If you apply the angle operator to the ARGV special filehandle, this operator returns undef at the end of the last input file, and eof() returns true at the very same time. On the other hand, eof returns true at the end of each input file, and there is no way to notice this, except for eof. (At least, I know no way to...) So, I think this advice is "avoid using eof(), because it is redundant with checking the return value of the angle operator". Is this right, or is there something I have overlooked? {599} First bullet item; Add a warning: But don't cache the results from gethostbyaddr too long. IP addresses _can_ change. Long-running daemons should attempt to honor the DNS TTL intent by rechecking the results of gethostbyaddr() or gethostbyname() hourly. [623] example in the middle: local($/) = LF; # not needed if $/ is already \012 I think there is a $ missing, and it should read local($/) = $LF; # not needed if $/ is already \012 (625) 4th bullet paragraph, code text, third example: open (FILE, "<" , $existing_file) or die $!; #righterer should read: open (FILE, "<" . $existing_file) or die $!; #righterer Concatination is required. (657) After "$digits"; Add: $0 - See $PROGRAM_NAME. (662) At the end of $EXECUTABLE_NAME/$X; Add: The name of the current perl script is stored in $0 ($PROGRAM_NAME). (679) First paragraph; Maybe there should be an executive decision to document _ALL_ of the the core functions in POD format, and not depend on system "man" pages. {691} after 2nd code block under "chown"; the code reads: chown($uidnum, $gidnum, 'file1', 'file2') == 2 or die "can't chown file1 or file2: $!"; and the text after it reads: "will set $cnt to 0,1, or 2..." where is the $cnt coming from? it's not even in the code. (693) 3rd paragraph: In the sentence "So if a close on a pipe returns a nonzero status,...", the phrase "nonzero status" should probably be replaced with "false value". The close() function returns a nonzero value on success; it is $! (not the return value of close()) that contains a nonzero value if there was an error with the pipe itself. (730) 4th paragraph; The fourth paragraph reads: "Here's how you might write a function that does a kind of set intersection by returning a list of keys occurring in all the hashes passed to it:" This description of the subroutine confused me quite a bit. The second half of the description---"returning a list of keys occurring in all the hashes"---appears to describe a union, not an intersection as first stated. I suggest something like: "returning a list of keys common to each of the hashes passed to it:" ?731? Third line on page; In the line sprintf "%lx", $number; # (That's an ell, not a one.) why is "l" being used at all? Doesn't the sprintf() function completely ignore the "l" qualifier? Under what circumstances does ell versus no-ell make any difference? ?754? table, end of row 4: Why is "1" not formatted CW (as the rest of the ISO number)? (767) "prototype" section, 2nd paragraph, 1st sentence: "the rest is taken as a name for Perl built-in" should be "the rest is taken as a name for a Perl built-in" {770} Second line before "readline" header; Change @dotfiles = grep { /^\./ && -f } map { "$path/$_" } readdir(THATDIR); to @dotfiles = grep { -f } map { "$path/$_" } grep { /^\./ } readdir(THATDIR); (777) "rindex" section, 2nd sentence: "if not SUBSTR is found" should be "if SUBSTR is not found." (777) End of "rmdir" section; The acronym PPT is not in the index and not defined anywhere. There really ought to be a URL pointing to the Perl Power Tools. (790) bottom of page: In some cases the hash variable is called %sales_amount and in others it is called %sale_amount. (792) last paragraph: "Schwartzian Transform" should be in the index. [800] srand function, third paragraph, first sentence: The sentence "You'll need something much more random than the default seed for cryptographic purposes" gives the dangerously misleading impression that the rand function is suitable for cryptographic purposes if initialized with a suitable seed. This is untrue. The third paragraph should be something along the lines of: Although the default value used for the random number seed (if srand is not called with later versions of perl) may be taken from a source of cryptographically-strong random numbers, that does not mean that the rand function is suitable for cryptographic purposes - far from it. If you need a source of cryptographically-strong random numbers, you should be accessing /dev/urandom directly, or checksumming the compressed output [... as before] There is also an omission in the description of srand, namely why one might wish to use it on later versions of perl in the first place. Something along the lines of: One use for srand, even on later versions of perl, is to ensure that you get the same sequence of seemingly-random numbers each time you run your program. This can be helpful when you need to debug a program which uses random numbers. Instead of having to replace the calls to rand with a subroutine that supplies numbers from a fixed list, you simply place say, srand(1);, at the start of your program. [805] code examples at bottom of substr function 8/00; To prepend the string "Larry" to the current value of $_ should be: To prepend the string "Larry" to the current value of $var and To instead replace the first character of $_ with "Moe" should be: To instead replace the first character of $var with "Moe" (806) "syscall" section, 1st sentence: "list passes the remaining elements" should be "list, passing the remaining elements." [812] bottom of the page (in the "syswrite" section); The loop for copying an input handle to an output handle reads: while ($len = sysread FROM, $buf, $blksize) { if (!defined $len) { next if $! == EINTR; die "System read error: $!\n"; } ... } The problem is that sysread returns undef on error, and undef is false, so the "if (!defined $len)" will not be encountered on an error. Rather, the loop will exit silently, leaving an incomplete output file. I believe the loop should read: while ( 1 ) { $len = sysread FROM, $buf, $blksize); if (!defined $len) { next if $! == EINTR; die "System read error: $!\n"; } last if $len == 0; ... } I see that the corresponding error in the CookBook has already been spotted, and appears in that book's errata. ?812? 1.1-2: "the signal number that killed the process" -> "the number of the signal that killed the process" (Who killed?) {814} line -3: "LIST" should be italic. (815) footnote: The footnote sign/character could be better placed after "the epoch" instead of at the end of the sentence. (817) 1.4: "perllocalle" -> "perllocale" (817) End of "ucfirst" section; Suggestion for last sentence: which is equivalent to both "\u\L$word" and "\L\u$word". (820) 4th paragraph: The 4th paragraph contains a tautology: "The unpack function is also useful for plain text data, too, not ..." suggest it be changed to: "The unpack function is also useful for plain text data, not ..." (827) "wantarray" section, 2nd paragraph: "Here's are examples of typical usage" should be "Here are examples of typical usage." {843} 3rd program text display: The line is: use constant FOO => 4 I would expect a semicolon at the end of this, but there is none. ?848? 2.-2: This makes it particularly useful "it" is a bit unclear in this paragraph; could be changed to "the function" or similar. (848) 4.1: "a list key/value pairs" -> "a list of key/value pairs" (857) 4.2 (entry for "number"): This works is just like most regular ... Remove "is". {859} first code paragraph; The open brace symbol "{" after "->" is apparently misplaced. The code will not compile as is. The error message is "Missing right curly or square bracket ...." [867] table: The Getopt::Long and the explanation are in different table rows. ?868? line above 1st table: Why "IPC access"? Change "file, directory, and IPC access" to "file and directory access"? (876) 2nd-to-last paragraph, 2nd sentence: "run a couple different algorithms" should be "run a couple of different algorithms." {877} Top; Top of the page: $s = "." x $len; But $len is not defined. Looks like it should have been $size. (878) "Carp" section, 1st paragraph, last sentence: "Carp is great way to misdirect blame" should be "Carp is a great way to misdirect blame." (882) "Data::Dumper" section, last paragraph: "reproduces an faithful copy of the original" should be "reproduces a faithful copy of the original." (886) 3rd-to--last paragraph: "the use statement requests that a particular version" should be "the use statement requests a particular version" {887} 3.3: One closing ) is missing; line should read: if (open(FH, "< /nonesuch")) { warn "no /nonesuch: $!"; } {888} -1.-3: One closing ) is missing; line should read: if (not cmp("fileA", "fileB", sub {munge $_[0] eq munge $_[1]} )) { (889) The footnote; The footnote is another unindexed reference to the Perl Power Tools project. Like page 777, there ought to be a URL. [900] bottom of page, under the IPC::Open2 heading: $his_output = ; $his_output should be getting . close(README); local handle should be: close(HIS_OUT); [907] before "Socket" Heading; A description of the Shell module should appear after Safe and before Socket. Shell is listed in the table on page 869 but not described later in the chapter. (907) Code for "socket" example; It needs to be made clear that only one of the three consecutive sockaddr_in() calls should be done. $port = getservbyname('echo','tcp'); $sin = sockaddr_in($port,inet_aton("127.1")); [or] $sin = sockaddr_in(7,inet_aton("localhost")); # 'echo' is '7' [or] $sin = sockaddr_in(7,INADDR_LOOPBACK); # Packed string for "127.1" {908} example code, 6th and 7th lines: The code reads use Symbol "gensym"; $sym1 = getsym(); $sym2 = getsym(); I belive the correct syntax is use Symbol "gensym"; $sym1 = gensym(); $sym2 = gensym(); {913} User::pwent entry; Change if($pw->uid == 1 && &pw->dir = m# (bin|tmp)?$# ) { print "gid 1 on root dir"; } to if($pw->uid == 1 && &pw->dir = m# (bin|tmp)?$# ) { print "uid 1 on root dir"; } (or else, please explain the discrepancy between the condition and the printed string). (918) Repeat count in (un)pack overflows; The two messages for "Repeat count" belong on page 962. ?935? Bad evalled substitution pattern: Shouldn't that appear on page 924? ?940? %s failed--call queue aborted: Shouldn't that appear on either page 920 ("%s") or page 941 ("failed")? {943} glob failed, line 7: "csh" should be italic (as on the other lines of this section). (955) Out of memory during ridiculously large request; Add sentence at end: If your program legitimately needs more than 2**31 bytes, you will need to recomple perl with "-Duse64bitall". {977} Middle of "perl: warning: Setting locale failed."; Change "set up the so-called variable system" to "set up the so called locale system". (979) architecture.1: "compluter" -> "computer" {980} ARGV; @ARGV is the name of the array. $ARGV is the scalar containing the name of the current input file. ?981? 4th item in the second column; big-endian ... Often considered superior to little-endian ... ... and on page 994: little-endian ... Often considered superior to big-endian ... ... Depending on how you look at it, these statements may be considered contradictory, or maybe complimentary, or maybe something else. Is that what the authors really wanted to write? (981) bind; Add the following sentence (which is really not a non-sequiteur): And remember that _my_, _our_, and _local_ bind tighter than the comma operator. May also want to mention that "bind" is the action performed by the Binding Operators (=~ and !~). [985] context entry; Void context is defined twice, the first time as a context category by itself (line 6), and then as a subcategory of scalar context (lines 8-9). Which is the right one? (992) JAPH "Just Another ... seen in Usenix signatures." Perhaps you meant "Usenet" signatures? (994) "magical variables" entry; Change %ENV array to %ENV hash [996] "open source software" entry; The rule for hyphenating URLs should be "Never hyphenate an URL. You can split it before or after a slash, but never hyphenate it." In this particular case, change http://www.open-source.org/ to http://www.opensource.org/ (998) polymorphism; The third word from the end of the paragraph looks garbled. ing on its type [