Programming Perl, 2nd Edition by Larry Wall, Tom Christiansen, and Randal Schwartz The 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 March 1, 2004. 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: (reader suggestion) You may want to add this to the list of Shell Traps in the Camel Book. It has "bit" me on several occasions. $? does not contain the return value of the last perl function or subroutine executed. It contains the status of the last pipe close, backtick or system() call executed. {8} (around line 15): The comma at the end of the line "Sat" => "Saturday", should be deleted. It's not really wrong, but it looks bad. {17} 7: The line that reads: $val ||= "2"; #Set $val to 2 if it isn't already set. is misleading because it will also set $val to 2 if $val is already set to 0. It should read: $val ||= "2"; #Set $val to 2 if it isn't already set or set to 0. (21) 1st paragraph, line 2: "awhile" should be "a while." (22) 1st paragraph: "logic operator" should be "logical operator" (twice). (37) 3rd paragraph, line 1: "nine constructs" should be "ten constructs." (38) 2nd para: "Names that start with anything else ..." is not quite right as it stands, because there are the special variables like $^T and $^O. (Chapter 3): In the list of functions by category at the start of chapter 3, the divisions don't make sense. "Fetching user and group information" has endhostent and endnetent, while "Fetching network information" has gethostent, sethostent, getnetent, and endnetent. I don't know exactly what these functions do, but the similarly named ones are all described on the same page. <43> First line of code under "'Here' Documents": The comment mentions an earlier example, but there doesn't seem to be a relevant earlier example. (51) 2nd paragraph, line -3: "%HASH" should be "%hash". [55] last paragraph: but you can't say <$foo> because that's an indirect filehandle Something seems to be missing here, maybe a * character? It occurs in a discussion about filename globbing, and the text does not say what $foo contains. Elsewhere on the page, you _can_ say <$foo> (3rd paragraph). {56} 6'th paragraph; ($file) = ; # list context should be (@file) = ; # list context (60) paragraph -1, line3: "if Engine" should be "if the Engine." (61) paragraph 5, line 1: "it either it matches or" should be "it either matches or it." {62} table of assertions: Second to last entry in table is (?...), should be (?=...) <64> paragraph 4, line5: After "A \b means a backspace in a character class" add ", not a word boundary." (66) paragraph 1, line 4: "bracket match" should be "paranthesis match." (66) There is one line I think is unclear. As an example, you have the following: /^(\d+\.?\d*|\.\d+)$/; # match valid number What this should really say is that this matches a valid *positive* number. This will not match negative numbers. To match all postive and negative valid numbers, you should say: /^-?(\d+\.?\d*|\.\d+)$/ (67) paragraph 1, line -1: "There's an" should be "This is an." (69) paragraph 3, line 2: "(1) question" should be "(1) the question." (71) code 2: "match the both `is'" should be "match both `is'." (71) code 2: "paragrep mode again" should be "paragraph mode again." {71} the example at the bottom of the page: The example for finding duplicate words will not work for single character words. For example: "The example has a a mistake in it and won't catch this line." "Nor this 1 1." The offending fragment is line 8 of the example--it picks up only words of 2 or more characters: (\w\S+) # find wordish chunk Either of these work: (\w\S*) # find wordish chunk (\S+) # find wordish chunk (77, 90, and index (and elsewhere?): There's no documentation for the range operator ... (as distinct from ..). It's in the online documentation for Perl 5.005 and it's mentioned in "Perl Cookbook" recipe 6.8. {94} The last paragraph begins: "There is also a logical xor operator that has no exact counterpart in C or perl, ...." If "xor" is in the perl language, there _is_ an exact counterpart, isn't there? (97) 1st paragraph: Bh01.LOCK => BLOCK {105} paragraph -4: In the paragraph beginning "You might think it odd," the word "foreach's" should be changed to "for's". {117} 4th paragraph, third indented example: This example reads ($aref, $bref) = func(\@c, \@d); print "@$aref has more than @$bref\n"; ... However, if @c has the same number of elements as @d, then the text of the print statement will be incorrect. Instead, it could read print "@$aref has at least as many as @$bref\n"; {120} Chapter 2: The Gory Details -- Subroutines (Prototypes) There is a program listed: 1) sub try (&$) { 2) my($try,$catch) = @_; 3) eval { &$try }; 4) if ($@) { 5) local $_ = $@; 6) &$catch; 7) } 8) } 9) sub catch (&) { @_ } 10) 11) try { 12) die "phooey"; 13) } catch { 14) /phooey/ and print "unphooey\n"; 15) }; If you run this program, you'll receive an run-time error something like this: ===== Undefined subroutine &main::1 called at ./test.pl line 8. ===== This is because of the prototype on subroutine "try". Line 1) The prototype (&$) forces the second parameter to be in scalar context. Line 9) "catch" returns the array of its parameters, @_. That array is then passed to try in scalar context. When an array is passed in scalar context, it returns the number of elements on the array. Line 2) So then the variable $catch in the subroutine "try" actually does not contain a subroutine reference but a scalar "1". Line 6) When &$catch is called, perl treats this as a symbolic reference to a subroutine named 1. Since there is no subroutine in the main namespace named 1, perl dies with an error. This can be fixed in a number of ways. (TMTOWTDI :) ) Two of the ways that will keep from changing the main executable program are: ========== *) Change Line 1: Line 1) sub try (&@) { +++) This will cause perl to pass the array returned by catch in list context. Passing an array in list context will maintain all of the elements, so the original subroutine reference is actually passed correctly to try. ========== OR (really this should be an AND/OR, but I think OR is more appropriate here) ========== *) Change Line 9: Line 9) sub catch (&) { $_[0] } +++ By returning a scalar, nothing is lost when the scalar returned by catch is passed in scalar context to subroutine try. The function reference actually gets passed and the program runs. ========== Personally I like the former change better than the latter. If it were me, I would make the first change and then make a special note saying that if that second parameter were a scalar then the program would have a run-time error. (And then point out why) I feel that this is an important correction as it can confuse the reader who is new to perl prototypes. (Because this error is a GREAT example of how the $ scalar prototype FORCES the second parameter into scalar context) [136] $[ section: It mentions that $[ is a compiler directive, but it doesn't tell you the real significance of this. What it really means is that if the compiler sees it, while parsing the program, it will generate code differently, even if the statement is in a subroutine that never gets called. Sure, it's deprecated, but the official tool a2p uses it, and that's how I got into trouble. I imported an awk script as a subrotine into my program by running a2p on it and then creating a closure around it. The subroutine only gets called under rare circumstances, and then only in a child created as a pipe. (This saved me from having to deliver two files.) But after I did this, things like ARGV[1] and substr didn't work any more in program code after the new subroutine. It took quite a while to pin down, but the 'compiler directive' statement in the book was the clue, and by setting $[ back to 0 at the end of the subroutine, everything was hunky dory again. I think there should be some discussion of this. And $[ is mentioned a number of other times in the book; I think more of them should be referred to in the index. {137} for $^I it says: The current value of the inplace-edit extension. Use undef to disable inplace editing. (Mnemonic: value of -i switch). What this doesn't say explicitly is that if you _set_ $^I you _enable_ inplace editing. The text as written can be interpreted as meaning that you must use the -i switch, at which point the value of $^I contains the value of the extension named with the switch (e.g. -i.bak) and undefing $^I disables inplace editing at that point. It would be helpful to include text to the effect that you don't need to use -i _iff_ you set $^I instead. {144-145} There are several functions listed in "Perl Functions by Category" that are not described in "Perl Functions in Alphabetical Order": - Flow of program control: continue - Fetching user and group information: entgrent, endhotsnt, endnetent, endpwent, setgrent, setpwent - Fetching network information: endproent, endservent, sethostent, setnetent, setprotoent, setservent {161} code sample 3: eval "\$$arrayname{\$key} = 1"; This doesnt work! If $arrayname isnt a hash(which it shouldnt be), Perl expands that to: eval "$ = 1"; Which perl does not like at all. A bit of experimenting proves the correct syntax to be: eval "\$$arrayname\{$key\} = 1"; Effectively keeping perl from expanding "arrayname" as a hash. {165} Next to last line;: In the sample fcntl call, &F_SETFL should be &F_SETFD. Also, the preceding statement that "Perl always sets the close-on-exec flag for file descriptors above 2" appears to be incorrect for version 5.004_04. Using this bit of code: pipe PARENT_READER, CHILD_WRITER; fcntl CHILD_WRITER, &F_SETFD, 1; ($pid = fork) >= 0 or die "fork: $!"; if($pid == 0) { close PARENT_READER; exec @ARGV or do { print CHILD_WRITER " "; exit 1; } } close CHILD_WRITER; (read PARENT_READER, $childError, 1 > 0) and exit 1; The parent process blocks on the read if the fcntl call is removed (i.e. CHILD_WRITER appears to remain open in the exec'ed process). {181} middle of page "join": in the first addition: join $_ =join':',($login,$passwd,etc); second addition: $_ =join':',$login,$passwd,etc; The first one works; the latter does not. ?185? description of localtime(): "... and the year has had 1,900 subtracted from it." The text is exactly right, but the wording had to leave me thinking: "Are they saying that because we are in the 1900's and that value would be different after the year 2000 or did they literally mean the fixed value 1,900?" Since so many people are and will be concerned with year 2000 issues over next few years, I thought maybe some extra wording might be helpful to users. {186} m// is missing from the functions list. {193} The code example is not -w clean. {194} code sample 1: open(FOO, "|tr '[a-z]' '[A-Z]'"); open(FOO, "|-") or exec 'tr', '[a-z]', '[A-Z]'; open(FOO, "cat -n file |"); open(FOO, "-|") or exec 'cat', '-n', 'file'; does not match the code on the WebMaster CD-ROM. In particular the following, "or" in line 2 and line 4 should be "||". {200} printf description: The syntax description was "corrected", and though the change certainly makes the syntax clearer, it now renders the description's comparison to print/sprintf incorrect (where does the format go?). <202> When discussing the "rand" function, the text reads "To get an integral value..." I'm thinking that perhaps you all meant "integer" instead of "integral" This is confusing because in Matlab, the "int" function is for integral, but for c, int is a data type for integer. {230} 5th paragraph: the code: @args = ("command", "arg1", "arg2"); system(@args) == 0 or die "system @args failed: $?" is not terminated with a semicolon. {237} in the description of unpack: For example, the following computes the same number as the System V sum program: undef $/; $checksum = unpack ("%32C*", <>) % 32767; For the System V systems that I have access to, the modulus should be 65535. This is also the same number as produced by the berkeley 'cksum -o 2'. (251) halfway down on the right: "If you want the C notion..." should read "If you want the C notation..." {268} first example line: foreach $i ( 0 .. $#{ $HoL{$family} ) { should be foreach $i ( 0 .. $#{ $HoL{$family} } ) { (268) top code segment (this is the 7/99 printing): I think the authors wanted to put print "\n"; at the end of the outer `for' loop, and not outside both loops. Indeed, with the input file a: b c b: c d c: d e d: e: and with the code in the book, I get the output a: 0 = b 1 = cb: 0 = c 1 = dc: 0 = d 1 = ed: e: which is probably not what the authors intended. Moving 'print "\n"' to the place I am suggesting, I get a: 0 = b 1 = c b: 0 = c 1 = d c: 0 = d 1 = e d: e: which I think the authors wanted (though I'd prefer not to see spaces around "="---which is what the authors do in later examples for HoH). {275} I think I found an error in the code # print the whole thing foreach $family ( keys %TV ) { print "the $family"; print " is on during @{ $TV{$family}{nights} }\n"; print "its members are:\n"; for $who ( @{ $TV{$family}{members} } ) { print " $who->{name} ($who->{role}), age $who->{age}\n"; } - --> print "it turns out that $TV{$family}{lead} has "; print scalar ( @{ $TV{$family}{kids} } ), " kids named "; print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } ); print "\n"; print "\n"; } It gave me this error with Perl 5.005_3: Use of uninitialized value at ./p275 line 68. I was able to correct it via changing the line to a for loop as follows: # print the whole thing foreach $family ( keys %TV ) { print "the $family"; print " is on during @{ $TV{$family}{nights} }\n"; print "its members are:\n"; for $who ( @{ $TV{$family}{members} } ) { print " $who->{name} ($who->{role}), age $who->{age}\n"; } - --> for $who ( @{ $TV{$family}{members} } ) { - --> if ( $who->{role} eq "lead" ) { - --> print "it turns out that $who->{name} has "; - --> last; - --> } - --> } - --> #print "it turns out that $TV{$family}{'lead'} has "; print scalar ( @{ $TV{$family}{kids} } ), " kids named "; print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } ); print "\n"; print "\n"; } [318] Example under heading Instance Variable Inheritance: I RAN THE SAMPLE: package Base; sub new { my $type = shift; my $self = {}; $self->{buz} = 42; return bless $self, $type; } package Derived; @ISA = qw(Base); sub new { my $type = shift; my $self = Base->new; $self{biz} = 11; return bless $self, $type; } package main; $a = Derived->new; print "buz = ", $a->{buz}, "\n"; print "biz = ", $a->{biz}, "\n"; NO VALUE APPEARS FOR $a->{biz} (333) -1(octnum) is alphabetized as if it were an el. It's a one. {349-350} The example code for the server contains the line print CLIENT "Hello there, $name .... It should read print Client "Hello there, $name .... {350} 10th line of code in first example: The non-forking server contains a call to REAPER on the SIG{CHLD} handle, even though that code is not in the non-forking version, and that version never spawns any children. {353} The server code is missing lots of other declarations; it does not compile on its own. The authors mention this after the code, but I missed it the first time. The example should either be more vague (don't have the shebang which suggests that the code is complete) or more explicit. Also, the $paddr variable is not declared. {437} 4th paragraph: The value of $path in the example should have a "/" at the end. Should read: $path eq '/virgil/aeneid/', {440} In the description of File::Find, which begins on p. 339, the very first line reads: chdired to $File::Find::dir when find() is called. It should read: chdired to $File::Find::dir when wanted() is called. {443} The 9/96 printing lists supposed Perl built-in functions like gets which are not described elsewhere. {451} 7th paragraph up from bottom, first line; This is in the second edition: $opt_foo = 'blech' should be $foo = 'blech' [497] Bottom: Please see description of problem in: http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/1999-12/msg00111.html Additionally Sleepycat reports that in multi-user environments they may have to close and reopen the database behind your back, in which case the lock is simply lost. (Mentioned again because it is not in your published errata, and because it appeared in the faq-o-matic on www.perl.com.) {537} paragraph -2: "$keyword{$_}" should be "$keywords{$_}". (608) indirect object: fonts messed up (or do I miss the joke?) (621) paragraph 1: "INChash" should be "INC hash." INDEX: The index is incomplete. For example these functions aren't there. The English names for a bunch of variables aren't there either, such as autoflush.index suggestion} an index entry for $#array pointing to the discussion on page 49 may help readers understand that is a special evaluation on arrays related to scalar evaluation. It is unrelated to the deprecated use of $# as a special variable. INDEX: May I suggest that touch (p. 239) be added to the index for the next Camel rev. This would be helpful for people who are looking up how to do this (and it is in italics after all :-) INDEX: Many of the references in the index table lead you to a page which does not conain the indexed word. (for example, in the index 'flush' is referenced at page 70, but nothing on that page.) {suggestion for future edition} Just a note to say: In a future addition of the Camel, please be sure to add move("/dev1/fileA","/dev2/fileB"); to the discussion of File::Copy in the Camel (p. 438). It's in the newer pod, so this may not even require a reminder, but I don't know how you do your minor revisions :-) (621) under \: Add an item "\1, \2, \3, ... (see backreferences)." (622) under $ variables: $& $' $` and $+ are on page 66, not page 65. (623) Because the use of the single quote in Perl4 has been changed to the double colon as the preferred delimiter, add "280" to the index entries for single quotes (on pages 623 and 641). (628) do SUBROUTINE operator: The do entry in the index should delete the word SUBROUTINE, as the pages cited are for the non-deprecated do block as well.