Errata

Programming Perl

Errata for Programming Perl, Fourth Edition

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

Color key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date submitted Date corrected
PDF
Page xxix
1st paragraph

"the perlthrtut manpage, which would have been approximately the same thing our ?Threads? chapter would have been."

This should read:

"the perlthrtut manpage, which is approximately the same thing our ?Threads? chapter would have been."

Note from the Author or Editor:
Change to read: "which is approximately the same thing as our".

Anonymous  Apr 03, 2012  Jun 15, 2012
PDF
Page 28
Last paragraph

The first sentence in the last paragraph references the wrong line number from the example program on page 19. It references line 15 when it should reference line 19.

Note from the Author or Editor:
Change as noted

ryanoz  Mar 13, 2012  Jun 15, 2012
PDF
Page 39
Second indented code example

Incorrect check for blank lines found:
next LINE if $line =~ "\n"; # skip blank lines
# This will obviously skip EVERY blank and non-blank line!

# First edition text was more correct (assuming no extra whitespace \n):
next LINE if $line eq "\n"; # skip blank lines

# or this even more correct:
next LINE if $line =~ "^\n$"; # skip blank lines

# or better yet (if 5.10 or later) this best solution:
next LINE if $line =~ "^\R$"; # skip blank lines

Note from the Author or Editor:
Change to =~ to eq, like

next LINE if $line eq "\n"; # skip blank lines

Anonymous  Aug 10, 2012  Jul 10, 2015
Printed
Page 45
3rd paragraph

End of Paragraph #3
================
So now you can probably figure out that when we said:
next LINE if $line =~ /^#/;
we meant "Go to the next iteration of LINE loop if this line happens to begin with a # character."

Discussion
=========
The above paragraph text refers to an outdated code example (from the 3rd edition of this book). The text should be updated to reflect the latest code example on page 39.

Note from the Author or Editor:
Change the text to read:

So now you can probably figure out that when we said:

last LINE if $line =~ /^>/;

we meant ?Go to the last iteration of the LINE loop if this line happens to begin with a > character.?

aphilipp  Mar 21, 2012  Jun 15, 2012
PDF
Page 88
2nd paragraph

The backtick example snippet at the top of the page says "perldoc $module", but the text two paragraphs below still says "The $user in our finger example above...", which refers to the example snippet given in the third edition.

Note from the Author or Editor:
Change as noted. Should read: "The $module in our perldoc example above..."

Anonymous  Feb 20, 2012  Jun 15, 2012
PDF
Page 89
4th paragraph

there is the words:
"Unless declared with my or
state, $_ is still a global variable, though, so functions called from INSIDE that
loop could still access it"

There must be "OUTSIDE that loop"

Note from the Author or Editor:
Change as noted

Dmitriy Koroliov  Jul 14, 2012  Jul 10, 2015
Printed
Page 104
3rd paragraph

"If $b is negative, then the result of $a % $b is $a minus the smallest multiple of $b that is not less than $a"

should be

"If $b is negative, then the result of $a % $b is $a minus the smallest multiple of the absolute value of $b that is not less than $a"

Discussion
=========
A multiple of a negative value will always result in a larger negative value. Because of this, if $a is positive and $b is negative, any multiple of $b will never result in a value that is not less than $a. Therefore, the absolute value of $b should be used when calculating the smallest multiple.

Note from the Author or Editor:
The suggested fix is necessary but insufficient. Replace both sentences at the end of the large paragraph ("If $b is positive... If $b is negative...") with the following text:

Unlike a mathematical remainder function, Perl's % operator defines
a sawtooth function on the real number line that drops to 0 at the
origin and at every multiple of the divisor, ramping up to just
under the divisor within each divisor interval. Unlike a remainder
function, it is not symmetric around 0, but continues the sawtooth
pattern on both sides of 0. Mathematically, $a % $b is therefore:

$a % $b == $a - ( floor($a / $b) * $b )

aphilipp  Mar 31, 2012  Jun 15, 2012
Printed
Page 110
last paragraph

"File ages for -M, -A, and -C are returned in days (including fractional days) since the script started running."

should be

"File ages for -M, -A, and -C are returned in days (including fractional days) since modification/last access/inode change until the script started running."

Note from the Author or Editor:
Change "File ages for -M, -A, and -C are returned in days (including fractional days) since the script started running" to read "File ages for -M, -A, and -C are returned in days (including fractional days) respectively between the last file modification, access, or inode change time and when the script started running."

aphilipp  Apr 02, 2012  Jun 15, 2012
Printed
Page 113
5th paragraph

"The "Matches" column is not always an exact rendition."

should be

"The "Like" column is not always an exact rendition."

Note from the Author or Editor:
Change as noted. [status=fixed in the source]

aphilipp  Apr 02, 2012  Jun 15, 2012
Printed
Page 116
2nd make_dogtag() example

The code doesn't actually do what is suggested: from the surrounding text it is clear that the code should check that all of the required fields are present (and not care about additional fields), but what it really does is only check that AT LEAST ONE of the required fields is present... this is clearly not what is asked of it.

Note from the Author or Editor:
Remove this text and replace it with nothing:

Or, if other fields are allowed but not required, use ARRAY ~~ HASH:
use v5.10;
sub make_dogtag {
state $REQUIRED_FIELDS = { name=>1, rank=>1, serial_num=>1 };
my ($class, $init_fields) = @_;
die "Must supply (at least) name, rank, and serial number"
unless [keys %{$init_fields}] ~~ $REQUIRED_FIELDS;
... }

Andrew Bryan  Mar 09, 2012  Jul 10, 2015
Printed
Page 117
2nd half of page

There seems to be conflicting descriptions of how objects on the left-hand of a smart match are handled:

Half way down the page it states:

"A left operand...falls back on... whatever the ref operator returns"

Yet the example at the end of the page showing a IO::Handle object being smart matched says the object is treated as a string:

"$fh as a string like IO::Handle=GLOB(0x8039e0)"

An object as a string like that is not what is returned by the ref operator.

I.e.

"$fh" eq "IO::Handle=GLOB(0x8039e0)"
ref($fh) eq "IO::Handle"

Note from the Author or Editor:
Change the next to last code segment to this (with proper alignment):

$object ~~ $number "$object" == $number
$object ~~ $string "$object" eq $string

The ref() goes away and the variable is surrounded by double quotes.

Andrew Bryan  Mar 09, 2012  Jul 10, 2015
Printed
Page 117
4th paragraph

"For simple strings or numbers, in becomes equivalent to this:"

should be

"For simple strings or numbers, it becomes equivalent to this:

Note from the Author or Editor:
Change as noted. [status=fixed in the source]

aphilipp  Apr 02, 2012  Jun 15, 2012
Printed
Page 119
Table 3-8

"True is exactly one of $a or $b is true, false otherwise"

should be

"True if exactly one of $a or $b is true, false otherwise"

Note from the Author or Editor:
Change as noted.

aphilipp  Apr 02, 2012  Jun 15, 2012
Printed
Page 123
1st paragraph

"it can be safely embedded within other expressions and functions calls"

should be

"it can be safely embedded within other expressions and function calls"

Note from the Author or Editor:
Change as noted.

aphilipp  Apr 09, 2012  Jun 15, 2012
Printed
Page 133-134
3 code examples

The code examples each read a line from standard input. Because there is a trailing newline at the end of the input string, the output of the warn statement is split into 2 lines. Perhaps the code can be modified by chomping the input string so that the warn statement outputs a single line.

Note from the Author or Editor:
On page 134, above both lines that begin with ?warn "unknown RGB...?, insert a new line at the same indentation level consisting entirely of

chomp;

aphilipp  Apr 10, 2012  Jun 15, 2012
PDF
Page 136
1st paragraph

"given(EXPR) assign the value"

should be

"given(EXPR) assigns the value"

Note from the Author or Editor:
Change as noted.

Anonymous  Apr 06, 2012  Jun 15, 2012
PDF
Page 138
3nd paragraph

The sentence reads, "But if EXPR2 does not get to use smartmatching, then the second argument will not get to either." I believe it should say EXPR1, not EXPR2.

Note from the Author or Editor:
Change as noted. Note that this sentence is in the 2nd paragraph, not the 3rd per the submitted location.

Anonymous  Feb 22, 2012  Jun 15, 2012
PDF
Page 141
1st code block

Some < and <= comparisons are missing a whitespace character.

page 141: $i<= 10
page 141: $i<= 10
page 141: $i< 32
page 144: $i< @ary1
page 144: $j< @ary2
page 370: $y< 13
page 371: $x<= 8
page 371: $y<= 12
page 371: $x<= 8
page 464: $i< @string
page 569: $i< 10
page 624: $i< 100
page 624: $i< 1000

Note from the Author or Editor:
Change all those to have a space right before the less-than symbol.

jlaire  Apr 13, 2012  Jun 15, 2012
PDF
Page 142
Center of page

On page 142 of the PDF version (and possibly all versions) of "Programming Perl", in Chapter 4, in the section on "foreach" loops, the following code is given as an example of a "for" (not foreach) loop:

for ($i=0; $i<$#ARGV; $i++)

That's not going to do what's intended; it will always ignore the last argument. To work as intended, it would have to be:

for ($i=0; $i<=$#ARGV; $i++)

This is probably due to the author being used to C in which one might write:

for ( i=0 ; i < ARGC ; ++i )

But in Perl, $#ARGV is always 1 *less* than the number of arguments because $#ARGV is "last index of @ARGV", not "number of elements of $#ARGV".

Note from the Author or Editor:
Update that line of code as noted to have the equal sign after the <

for ($i=0; $i<=$#ARGV; $i++)

Robbie Hatley  Mar 17, 2015  Jul 10, 2015
Printed
Page 152
last code example

sub unimplemented { ... }
eval { unimplemented() };
if ($@ eq "Unimplemented") {
say "Caught an Unimplemented exception!";
}

should be

sub unimplemented { ... }
eval { unimplemented() };
if ($@ =~ /\AUnimplemented/) {
say "Caught an Unimplemented exception!";
}

This change is required since the $@ variable contains more text than "Unimplemented". It contains something like the following:

Unimplemented at ./program.pl line 5.

Note from the Author or Editor:
Change
if ($@ eq "Unimplemented") {
to
if ($@ =~ /^Unimplemented/) {

aphilipp  Apr 14, 2012  Jun 15, 2012
Printed
Page 180
3rd paragraph

"because 255 might not be U+00FF LATIN SMALL LETTER Y (?) in the current locale"

should be

"because 255 might not be U+00FF LATIN SMALL LETTER Y WITH DIAERESIS (?) in the current locale"

Note from the Author or Editor:
Change as noted.

aphilipp  Apr 25, 2012  Jun 15, 2012
Printed
Page 182
first paragraph

The sentence containing "the six translation escapes" should instead read "the seven translation escapes".

Tom Christiansen
 
Jun 23, 2012  Dec 13, 2013
PDF
Page 193
2nd paragraph

"Table 5-3" should be "Table 5-9" in the following sentence?

An alphabetical list of these metasymbols can be found below in Table 5-3.

Note from the Author or Editor:
Change as noted

Anonymous  Feb 27, 2012  Jun 15, 2012
PDF
Page 196
Table 5-9. Alphanumeric regex metasymbols

Unintended space following "\" in these table entries:

\ NNN Yes Match the character given in octal, up to \377.
\ n Yes Match nth capture group (decimal).

and following "\c" in this table entry:

\c X Yes Match the control character Control-X (\cZ, \c[, etc.).

Note from the Author or Editor:
Changed as noted.

Anonymous  Feb 27, 2012  Jun 15, 2012
PDF
Page 197
Table 5-9

"\o{NNNN} Yes Match the character give in octal."

s/give/given/

Note from the Author or Editor:
Change as noted.

jlaire  Apr 07, 2012  Jun 15, 2012
PDF
Page 200
3rd paragraph

There's whitespace between ( and ":full", which seems unintentional.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 07, 2012  Jun 15, 2012
PDF
Page 200
last paragraph

"You can?t use the dot [in a bracketed character class] because it would match (nearly) any character in existence"

The dot can be used there and it matches a literal dot.

Note from the Author or Editor:
A clearer wording would be: "None of these may be used in their metacharacter sense in a bracketed character class."

jlaire  Apr 07, 2012  Jun 15, 2012
Printed
Page 201
last paragraph

The simplified regex give for \X of "(?\PM\pM*)>" has a misplaced >. It should instead read "(?>\PM\pM*)". Also, the entire thing should be in monospace.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 201
last paragraph

The regexp at the bottom of the page that reads "| \p{Grapheme_Extend}" should instead read "| \p{Grapheme_Extend}+ | ." with the second "| ." occupying its own line and the pipe symbols in vertical alignment.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 203
last paragraph

A character class also allows any metasymbol representing a specific set of characters, including negated classes like \P{NOPROP}, \N, \S, and \D ...

But character class does not allow \N. Perl throws this error:

\N in a character class must be a named character: \N{...} in regex;

Note from the Author or Editor:
Change:

including negated classes like \P{NOPROP}, \N, \S, and \D

To make the \N a \W instead:

including negated classes like \P{NOPROP}, \W, \S, and \D

Dmitriy Koroliov  Aug 07, 2012  Jul 10, 2015
Printed
Page 204
2nd paragraph

The phrase at the start of the second line of the second paragraph that reads "Unicode names sequence" should instead read "Unicode named sequence".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 206
6th paragraph

"That means a codepoint like U+0389, GREEK CAPITAL LETTER OMEGA, is always a \w character."

should be

"That means a codepoint like U+03A9, GREEK CAPITAL LETTER OMEGA, is always a \w character."

Note from the Author or Editor:
Change as noted.

aphilipp  May 03, 2012  Jun 15, 2012
Printed
Page 207
first line of code paragraph

The regex "/^\pL\N/" should read "/[^\pL\pN]/".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 208
last line on page

"Joining punctuation an like underscore" should read "Joining punctuation like an underscore"

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 210
end of second paragraph

The sentence that ends with "section in 15." should read "section on page 309 in Chapter 6."

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 210-211
Table 5-14

The entries under the last column, labelled Name, should be set in small capitals.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 210
1st code example

chr(0x110000) =~ \p{ahex=true} # false
chr(0x110000) =~ \p{ahex=false} # false!

chr(0x110000) =~ \P{ahex=true} # true
chr(0x110000) =~ \P{ahex=false} # true!

should be

chr(0x110000) =~ /\p{ahex=true}/ # false
chr(0x110000) =~ /\p{ahex=false}/ # false!

chr(0x110000) =~ /\P{ahex=true}/ # true
chr(0x110000) =~ /\P{ahex=false}/ # true!

Note from the Author or Editor:
Change as noted.

aphilipp  May 08, 2012  Jun 15, 2012
PDF
Page 211
2nd paragraph

"The second column in Table 5-15 shows the POSIX classes available as of v5.14."

s/second/first/

Note from the Author or Editor:
Change as noted.

jlaire  Apr 08, 2012  Jun 15, 2012
Printed
Page 212
1st paragraph, 1st column

The phrase in the table reading "occurring continuous ranges" should read "occurring in continuous ranges".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 213
Table 5-15. POSIX character classes (last entry)

The term "xdigit" broken into "xdi" and "git" in the following table entry:

xdi
git

Any hexadecimal digit, either narrow ASCII
characters or the corresponding fullwidth
characters.

Note from the Author or Editor:
&#10003; The column width on this table's first column needs to be widened to make sure that "xdigit" all fits on one line.

Anonymous  Feb 28, 2012  Jun 15, 2012
Printed
Page 213
Table 5-16

[^:digit:]
[^:space:]
[^:word:]

should be

[:^digit:]
[:^space:]
[:^word:]

Note from the Author or Editor:
Change as noted.

aphilipp  May 09, 2012  Jun 15, 2012
PDF
Page 224
1st paragraph

"the + quantifiers? repetitions"

s/s'/'s/

Note from the Author or Editor:
Change as noted.

jlaire  Apr 08, 2012  Jun 15, 2012
PDF
Page 224
-1st code snippet

Many code snippets that used "print" in the 3rd edition have been changed to use "say". However, the "say" feature is not always enabled, even in complete examples that start with a shebang. Futhermore, some of these scripts wouldn't work with "use v5.14" because of undeclared variables.

I haven't read the whole book, but I searched the PDF for "#!/" and found code snippets that seem to suffer from this problem on pages 224-225, 251, 253, 259-260, 745-746, and 909.

I've previously submitted an errata for the one on page 253.

Note from the Author or Editor:
On page 224, just below the #!/usr/bin/perl line, insert this line:

use feature "say";

On page 251, just below the #!/usr/bin/perl ?00p line, insert this line:

use feature "say";

On page 253, just below the #!/usr/bin/perl line, insert this line:

use feature "say";


On page 259, just below the #!/usr/bin/perl line, insert this line:

use feature "say";

On both pages 745 and 746, just below the #!/usr/bin/perl line, insert this line:

use v5.14;

Also, change the "my" to a "state" on both those variables, so that it now reads:

state $count = 0;

On page 909, right after the #!/usr/bin/perl line, insert this line:

use v5.14;

jlaire  Apr 09, 2012  Jun 15, 2012
Printed
Page 225
last code example

The outer set of noncapturing parentheses in the following line of code seems to serve no purpose:

my $dupword = qr{ \b (?: ( \w+ ) (?: \s+ \g{-1} )+ ) \b }xi;

Wouldn't it be better written as follows?

my $dupword = qr{ \b ( \w+ ) (?: \s+ \g{-1} )+ \b }xi;

Note from the Author or Editor:
Change as noted.

aphilipp  May 13, 2012  Jun 15, 2012
Printed
Page 227, 228
2nd paragraph, 4th paragraph

The following lines of text are at issue:

"If you happen to have more than one group by the same NAME in the same pattern, then %+ holds only the last string captured"

"Which makes $+{name} the same as $-{name}[-1]. It's also the same as $-{name}[$#{$-{name}}]"

My finding is that %+ holds the first string captured, and not the last. I am not sure if this is intended Perl functionality or if it is a bug.

Note from the Author or Editor:
Change "then %+ holds only the last string captured" to "then %+ holds only the first string captured" instead.

Change "Which makes $+{name} the same as $-{name}[-1]. It's also the same as $-{name}[$#{$-{name}}]" to just "Which makes $+{name} the same as $-{name}[0]."

aphilipp  May 14, 2012  Jun 15, 2012
PDF
Page 228
5th paragraph

"the standard Tie:Hash::NamedCapture module"

The first colon looks lonely. s/:/::/

Note from the Author or Editor:
Change as noted.

jlaire  Apr 08, 2012  Jun 15, 2012
Printed
Page 228
code section at bottom

The CPAN documentation for the Tie::Hash::NamedCapture module contains the following:

"When the all parameter is omitted or false, then the tied hash elements will be the contents of the leftmost defined buffer with the name of the associated hash key."

Therefore, the "%last_captured" hash would be more appropriately named something like "%first_captured".

Note from the Author or Editor:
Change all three instances of "last_captured" in the code on page 228 to read "first_captured" instead.

aphilipp  May 15, 2012  Jun 15, 2012
Printed
Page 228
6th paragraph

"Now access your named captures through those variables, just as you did with $+ and %+, but using your own names."

should be

"Now access your named captures through those variables, just as you did with %+ and %-, but using your own names."

Note from the Author or Editor:
Change as noted.

aphilipp  May 15, 2012  Jun 15, 2012
Printed
Page 228
1st paragraph

Since the %+ variable holds only the first string captured, it does not get overwritten when you have the same named group loaded more than once. Therefore the following sentence should be rewritten:

"When you have the same named group loaded more than once, the previous contents in the %+ variable are overwritten, just like assigning to a scalar more than once."

Note from the Author or Editor:
Change this sentence:

When you have the same named group loaded more than once,
the previous contents in the %+ variable are overwritten, just like assigning to a
scalar more than once.

to read:

When you
have the same named group loaded more than once, the previous
contents in the %+ variable are
not overwritten; only the first one counts.

aphilipp  Jun 04, 2012  Jun 15, 2012
Printed
Page 230
7th paragraph

Delete the two words "other modifiers", because "modifiers" occurs after the list.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 236
3rd paragraph, 2nd line

Change "six translation escapes" to "seven translation escapes".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 236
3rd paragraph, 6th line

Change "Table 5-3" to "Table 5-9".

Note from the Author or Editor:
Change as noted.

aphilipp  May 22, 2012  Jun 15, 2012
PDF
Page 237
-1st paragraph

"patterns that were more than 10k longer"

s/longer/long/ (or some other wording)

Note from the Author or Editor:
Change "more than 10k longer" to "over 10k in length".

jlaire  Apr 08, 2012  Jun 15, 2012
PDF
Page 245
4th bullet in 4th (?) paragraph

I think the following refers to Table 5-9 instead of 5-3:

A backslashed letter matches an abstract sequence, typically either a
particular character or one of a set of characters, as listed in Table 5-3.

Note from the Author or Editor:
Change as noted

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 248
2nd regex example on the page

The regex example::
"0123456789" =~ /(?:(\d{3}))/g
should be:
"0123456789" =~ /(?=(\d{3}))/g

Note from the Author or Editor:
Change as noted.

Anonymous  Feb 26, 2012  Jun 15, 2012
PDF
Page 248
-1st paragraph

"When the Engine encounters (?<= PATTERN)"

Superfluous space before PATTERN. The header doesn't have a space there, and neither do the similar sentences about (?=PATTERN) and (?!PATTERN).

Same thing on page 249, 4th paragraph:

"When the Engine encounters (?<! PATTERN)"

Note from the Author or Editor:
Change as noted.

jlaire  Apr 09, 2012  Jun 15, 2012
Printed
Page 248
line that reads "0123456789" =~ /(?:(\d{3}))/g;

The line that reads

"0123456789" =~ /(?:(\d{3}))/g;

Should have an equal sign, not a colon after the question mark, as follows:

"0123456789" =~ /(?=(\d{3}))/g;

Note from the Author or Editor:
Change as noted

Leonard Cuff  Dec 31, 2012  Jun 15, 2012
Printed
Page 249
3rd paragraph, 3rd line

Change "for left to right" to "from left to right".

Note from the Author or Editor:
Change as noted.

aphilipp  May 27, 2012  Jun 15, 2012
PDF
Page 250
4th paragraph

"Although (?> PATTERN) is useful"

Superfluous space before PATTERN.

(I searched for ' PATTERN)' in the PDF and didn't find any more.)

Note from the Author or Editor:
Change as noted.

jlaire  Apr 09, 2012  Jun 15, 2012
PDF
Page 252
6th paragraph

Here's a list of straight quotes that should be curly quotes. I don't feel like flooding the errata list with separate submissions.

word: pages

it's: 252, 268, 713, 757, 805, 808, 810, 817, 868, 993, 1060
that's: 277
another's: 389
doesn't: 446
isn't: 655
programmer's: 675
you're: 759
he's: 904
here's: 1011
you'll: 1041

Note from the Author or Editor:
Change all the non-literals as noted.

jlaire  Apr 09, 2012  Jun 15, 2012
PDF
Page 253
4th paragraph (the code listing)

The '#' on the following line:

say "REGEX is $re\n"; # debugging output

is not aligned with the others, and the \n should be dropped.

(Compared to the 3rd edition, "print" has been changed to "say", but the \n and vertical alignment weren't updated to match.)

Note from the Author or Editor:
Change the say back to a print.

jlaire  Apr 09, 2012  Jun 15, 2012
Printed
Page 254
1st code section

Assuming Perl v5.14, change "REGEX is (?i-xsm:" to "REGEX is (?^ui:".

Note from the Author or Editor:
Change as noted.

aphilipp  May 27, 2012  Jun 15, 2012
Printed
Page 258
2nd code example

The output of the following line of code is different than what is described in the text:

"abcdef" =~ / .+ (?{say "Matched so far: $&"}) bcdef $/x;

The text states that this prints the following:

Matched so far: abcdef
Matched so far: abcde
Matched so far: abcd
Matched so far: abc
Matched so far: ab
Matched so far: a

But I am finding that only the last line gets printed:

Matched so far: a

Since this example was taken from the 3rd edition of this book, I suspect that it was not updated to reflect new optimizations to the regex engine. One solution to get the output that the text describes is to slightly modify the code example to the following:

"abcdef" =~ / .+ (?{say "Matched so far: $&"}) .cdef $/x;

Note from the Author or Editor:
Change as noted. That is, change the line reading:
"abcdef" =~ / .+ (?{say "Matched so far: $&"}) bcdef $/x;
to reading
"abcdef" =~ / .+ (?{say "Matched so far: $&"}) .cdef $/x;
by switching the second "b" in the line to a ".".

aphilipp  May 30, 2012  Jun 15, 2012
Printed
Page 259
1st code example

The following code example gives the error "Unmatched ) in regex":

$text =~ /( \(+ ) (.*?) (??{ "\)" x length $1 })/x;

This is because the backslash disappears when the (??{ CODE }) extension is evaluated. In other words, the "\)" becomes ")". To preserve the backslash, use single quotes instead of double quotes:

$text =~ /( \(+ ) (.*?) (??{ '\)' x length $1 })/x;

Note from the Author or Editor:
Change as noted.

aphilipp  Jun 01, 2012  Jun 15, 2012
PDF
Page 265
last code snippet (and the following pages)

I'm not familiar with the details of pod, but there are at least two obvious bugs. The code doesn't parse all the "hairy examples" on page 265, but with these bugs fixed it does.

1) The group named "mirrored" contains \s++\s+, which means it will never match, and \s+\s++, which is also wrong. For symmetry with the later Regexp::Grammars version, the \s++'s should be deleted.

This bug appears at the end of page 265 and also in the complete code listing on page 266.

2) The program on page 266 has a broken implementation of "balanced". It doesn't parse "C<xB<>>", because "unangle" is possessive and eats not only the "x" but also "B", which makes "podtag" fail. This could be fixed by e.g. changing "unangle"s definition from [^<>]++ to [^<>]+ or to (?>[^<>]+(?!<)).

The Regexp::Grammar version on page 268 is broken in this way, too.

--

The code also allows nesting "mirrored" inside "balanced", but I don't know if that's intentional. This is a nice example of regexes and grammars, but it would be cool if the input was more clearly defined in the text and the code actually worked on the pod examples given.

Note from the Author or Editor:
On page 266 replace the second plus with a space, changing

(?<unangle> [^<>]++ )

to

(?<unangle> [^<>]+ )

Also on page 266, delete both instances of \s++.

On page 268, remove the second plus, changing

<token: unangle> [^<>]++

to just

<token: unangle> [^<>]+

On page 269, this unified diff should be applied:

--- /tmp/t0 2012-06-12 11:40:36.000000000 -0600
+++ /tmp/t1 2012-06-12 11:40:53.000000000 -0600
@@ -28,15 +28,26 @@
},
}
{
- "" => "N<inside>",
+ "" => "I<< N<inside>un>tag >>",
"podtag" => {
- "" => "N<inside>",
- "capital" => "N",
+ "" => "I<< N<inside>un>tag >>",
+ "capital" => "I",
"either" => {
- "" => "<inside>",
- "balanced" => {
- "" => "<inside>",
- "contents" => { "" => "inside", "unangle" => ["inside"] },
+ "" => "<< N<inside>un>tag >>",
+ "mirrored" => {
+ "" => "<< N<inside>un>tag >>",
+ "open" => "<<",
+ "podtag" => {
+ "" => "N<inside>",
+ "capital" => "N",
+ "either" => {
+ "" => "<inside>",
+ "balanced" => {
+ "" => "<inside>",
+ "contents" => { "" => "inside", "unangle" => ["inside"] },
+ },
+ },
+ },
},
},
},

At which point the entire output should look like this:

{
"" => "C<B<nested>>",
"podtag" => {
"" => "C<B<nested>>",
"capital" => "C",
"either" => {
"" => "<B<nested>>",
"balanced" => {
"" => "<B<nested>>",
"contents" => {
"" => "B<nested>",
"podtag" => [
{
"" => "B<nested>",
"capital" => "B",
"either" => {
"" => "<nested>",
"balanced" => {
"" => "<nested>",
"contents" => { "" => "nested", "unangle" => ["nested"] },
},
},
},
],
},
},
},
},
}
{
"" => "I<< N<inside>un>tag >>",
"podtag" => {
"" => "I<< N<inside>un>tag >>",
"capital" => "I",
"either" => {
"" => "<< N<inside>un>tag >>",
"mirrored" => {
"" => "<< N<inside>un>tag >>",
"open" => "<<",
"podtag" => {
"" => "N<inside>",
"capital" => "N",
"either" => {
"" => "<inside>",
"balanced" => {
"" => "<inside>",
"contents" => { "" => "inside", "unangle" => ["inside"] },
},
},
},
},
},
},
}
{
"" => "X<indexed>",
"podtag" => {
"" => "X<indexed>",
"capital" => "X",
"either" => {
"" => "<indexed>",
"balanced" => {
"" => "<indexed>",
"contents" => { "" => "indexed", "unangle" => ["indexed"] },
},
},
},
}

jlaire  Apr 09, 2012  Jun 15, 2012
PDF
Page 267
2nd paragraph

The phrase "pieces you that you've" looks incorrect in the following sentence (remove "you"?):

So while you can use this technique to validate input, it has its points of frustration
when it comes to pulling out the pieces you that you?ve just worked so hard
to parse.

Note from the Author or Editor:
"pieces you that you've" should have the first "you" removed.

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 271
sentence just above the "Alternate Engines" header

This sentence probably intends to refer to chapter 7:

Now if you?re still wondering what those sub thingies are in the Tagger module, you?ll find out soon enough because that?s what Chapter 6 is all about.

Note from the Author or Editor:
Change as noted

Anonymous  Feb 26, 2012  Jun 15, 2012
Printed
Page 272
2nd paragraph

The phrase "maintains a high level Perl compatibility" is missing the word "of" and so should read "maintains a high level of Perl compatibility".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 273
RE2 code examples

The three RE2 examples are each have a "/dev/null" where they should have ">/dev/null". (Also, the ">/dev/null" should be shown in bold type.)

Note from the Author or Editor:
The "/dev/null" in the second group of examples should be part of the command line, as in the first group. It should be ">/dev/null" as noted.

Anonymous  Feb 26, 2012  Jun 15, 2012
PDF
Page 280
second to last code

The string literal assigned to $motto should have spaces between the characters, like it does in the versions using charnames and magic numbers.

Note from the Author or Editor:
Easier, and perhaps better, to take the spaces out of the \x and \N versions of $motto.

jlaire  Apr 11, 2012  Jun 15, 2012
PDF
Page 282
5th paragraph

The following sentence:

On input, the :crlf layer translates \n into \r\n; on output, it does the opposite.

appears to be saying the opposite of what :crlf really does, as per the docs:

PERLIO_F_CRLF

Layer is performing Win32-like "\n" mapped to CR,LF for output and CR,LF mapped to "\n" for input.)

-- http://perldoc.perl.org/perliol.html


Note from the Author or Editor:
Exchange the words "input" and "output" in the referenced sentence.

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 282
first code example

binmode STDOUT, ":encoding(UTF?8)"
|| die "can't binmode to UTF?8: $!";

Needs parens or 'or'.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 11, 2012  Jun 15, 2012
Printed
Page 283
end of 4th paragraph

Change "See 19." to "See Chapter 17."

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 285
3rd paragraph

In the following sentence, I think "seen" should be "see":

Alas, you?ll even seen ?text? files where
some lines have one encoding but other lines have different encodings.

Note from the Author or Editor:
"you?ll even seen" should read "you?ll even see".

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 287
1st code example

I cannot find a method by the name of "Filter_Value" in the DBM_Filter module documentation. I presume that the method "Filter_Value_Push" was meant to be used instead. Therefore the following change should be made:

$dbobj->Filter_Value("utf8");

should be

$dbobj->Filter_Value_Push("utf8");

Note from the Author or Editor:
Change as noted

aphilipp  Jul 22, 2012  Jul 10, 2015
PDF
Page 288
3rd paragraph, 3rd line

Change "two string" to "two strings".

Note from the Author or Editor:
Change as noted

aphilipp  Nov 27, 2012  Jul 10, 2015
PDF
Page 290
1st paragraph

"That is, a single user-visible character (a grapheme) can require more than a single codepoint to represent."

should be

"That is, a single user-visible character (a grapheme) can require more than a single codepoint to represent it."

Note from the Author or Editor:
Change as noted

aphilipp  Jul 25, 2012  Jul 10, 2015
PDF
Page 290
4th paragraph, 6th line

Change "LATIN LETTER SMALL O" to "LATIN SMALL LETTER O".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 25, 2012  Jul 10, 2015
PDF
Page 291
5th paragraph

In the following sentence, I think it should read, "This may be what you want ...":

This may be want you want in searching and related
applications, but canonical decomposition normally works better than compatibility
decomposition for most applications.

Note from the Author or Editor:
""This may be want you want" should read "This may be what you want".

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 291
1st paragraph, 1st line

Change "LATIN LETTER SMALL E WITH ACUTE" to "LATIN SMALL LETTER E WITH ACUTE".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 25, 2012  Jul 10, 2015
PDF
Page 291
1st paragraph, 3rd line

Change "LATIN LETTER SMALL E" to "LATIN SMALL LETTER E".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 25, 2012  Jul 10, 2015
Printed
Page 293
Paragraph -3 (meaning three from the end)

There should be a comma between "combining characters" and "variation selectors".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
Printed
Page 293
last paragraph

"to know about more" should read "to know more about".

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 294
6th (?) paragraph (wild guess)

I believe the second comment below was intended to be "cr?me fra?che":

And change the last bit this way:
substr($cb, ?6) = "fra?che"; # "cr?me brfra?che" or "cr?me fra?che"
$cb =~ s/\X{6}$/fra?che/; # "cr?me br?l?e"

Note from the Author or Editor:
The comment "cr?me br?l?e" should read "cr?me fra?che".

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 294
2nd and 3rd bulleted list items

This escape sequence used in two regexes:

\x{COMBINING TILDE}

should be changed from \x{} to \N{}:

\N{COMBINING TILDE}

Note from the Author or Editor:
Change as noted.

Nick Patch  Apr 10, 2012  Jun 15, 2012
PDF
Page 294
code example between 1st and 2nd paragraph

Change "\x{COMBINING TILDE}" to "\N{COMBINING TILDE}".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 27, 2012  Jul 10, 2015
PDF
Page 294
2nd paragraph, 1st line

Change "strings comparisons" to "string comparisons".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 27, 2012  Jul 10, 2015
PDF
Page 296
1st code section

my $gs = Unicode::GCString("cr�me br�l�e");

should be

my $gs = Unicode::GCString->new("cr�me br�l�e");

Note from the Author or Editor:
Change as noted.

aphilipp  Jul 28, 2012  Jul 10, 2015
PDF
Page 296
2nd paragraph

This paragraph describes methods index and rindex that return integer offsets in graphemes instead of codepoints. These methods do not exist in the Unicode::GCString module.

Note from the Author or Editor:
Change first line of first code block

my $gs = Unicode::GCString->new("crème brûlée");

In the following paragraph, end the sentence by removing the clauses that mention index and rindex:

graphemes and the substr method operates on graphemes.

aphilipp  Jul 28, 2012  Jul 10, 2015
PDF
Page 296
6th paragraph, 5th line

Change "East_Asian_Width=Full" to "East_Asian_Width=Fullwidth".

Note from the Author or Editor:
Change per description.

aphilipp  Jul 28, 2012  Jul 10, 2015
PDF
Page 297
2nd paragraph, 4th line

Change "UAX#14" to "UAX #14".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 28, 2012  Jul 10, 2015
PDF
Page 297
2nd paragraph, 5th line

The book refers to the Unix program fmt(1) as being from the Text::Autoformat module. Looking at the CPAN documentation, I do not see anything to indicate that this module provides this program.

Note from the Author or Editor:
Change sentence:

like the Unix fmt(1) program of the Text::Autofor mat module.

to end after "program":

like the Unix fmt(1) program.

aphilipp  Jul 29, 2012  Jul 10, 2015
PDF
Page 298
6th paragraph

"Rider", and "Riding" should go together

should be

"Rider" and "Riding" should go together

Note from the Author or Editor:
Change as noted

aphilipp  Jul 30, 2012  Jul 10, 2015
Printed
Page 299
code section at bottom of page

The word "sub" was omitted right before the curly in "--preprocess => {"; that would be an anonymous hash, but it needs to be an anonymous subroutine, so it should read "--preprocess => sub {" instead.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 299
3rd code block

The second regex:

s/ ( \d+ ) / sprintf "%020d", $1 /g

requires the /x and /e modifiers:

s/ ( \d+ ) / sprintf "%020d", $1 /xeg

Note from the Author or Editor:
Change as noted.

Nick Patch  Apr 10, 2012  Jun 15, 2012
PDF
Page 299
3rd code block

The Unicode::Collate attribute keys:

--upper_before_lower => 1,
--preprocess => {

shouldn't be prefixed with "--":

upper_before_lower => 1,
preprocess => sub {

This is the only instance of Unicode::Collate in the book with this issue.

Note from the Author or Editor:
Change as noted.

Nick Patch  Apr 10, 2012  Jun 15, 2012
PDF
Page 299
code section at bottom of page

The penultimate line shouldn't have a semicolon.

Note from the Author or Editor:
Change the penultiumate semicolon to a comma. It should actually read:

my $collator = Unicode::Collate->new(
upper_before_lower => 1,
preprocess => sub {
local $_ = shift;
s/^ (?: The | An? ) \h+ //x; # strip articles
s/ ( \d+ ) / sprintf "%020d", $1 /gex;
return $_;
},
);

jlaire  Apr 12, 2012  Jun 15, 2012
PDF
Page 301
3rd paragraph

Change "differ" to "are the same" in the phrase "Only when primary strengths differ does it fall through to compare secondary strengths".

Note from the Author or Editor:
Change as noted.

Nick Patch  Apr 10, 2012  Jun 15, 2012
PDF
Page 303
4th paragraph, 7th line

Change "forwards compatibility" to "forward compatibility".

Note from the Author or Editor:
Change as noted

aphilipp  Jul 30, 2012  Jul 10, 2015
PDF
Page 306
4th (?) paragraph

The following refers to Table 5-6, and I think it might be Table 5-12 instead (not sure):

One thing to always be aware of is that, by default, the Perl shortcuts like \w, \s,
and even \d match many Unicode characters based on particular character properties.
These are described in Table 5-6, and are intended to match the formal
definitions given in Annex C: Compatibility Properties from Unicode Technical
Standard #18, ?Unicode Regular Expressions?, version 13, from August 2008.

Note from the Author or Editor:
It should refer to table 5-11, not to 5-6.

Anonymous  Feb 28, 2012  Jun 15, 2012
Printed
Page 307
The string in the code insert that gets assigned to $mystery.

The string that?s assigned to $mystery, on the line below the commented out "## NFD" should read "&#2413;??&#8047;". And earlier value from the top of the page was accidentally copied to the mystery string, and shouldn?t have been.

Tom Christiansen
 
Mar 30, 2012  Jun 15, 2012
PDF
Page 307
2nd code block

print " BC=", $$ci{bidi};
print " mirrored=", $$ci{bidi};

The second "bidi" should be "mirrored".

Also, the outputs on the following page should have newlines before each "gc", not "BC".

Note from the Author or Editor:
Change as noted.

jlaire  Apr 12, 2012  Jun 15, 2012
PDF
Page 307
2nd code section

The code has a newline and tab immediately after ' \N{%s}' and before " gc=". But most of the output on page 308 shows the newline and tab just before " BC=". The formatting of the output should match the code.

Note from the Author or Editor:
Break the lines on 308 before gc=, like

U+096D \N{DEVANAGARI DIGIT SEVEN}
gc=Nd script=Devanagari BC=L mirrored=L ccc=0 nv=7

aphilipp  Aug 11, 2012  Jul 10, 2015
PDF
Page 311
1st paragraph

Page 311 has the following sentence:

It?s important to remember not to use ?&? for the first set; that would be intersecting
with nothing, resulting in an empty set.

The preceding page (310) has this sentence:

Intersection, specified with the ?&" prefix, is useful for getting the common characters
matched by two (or more) classes.

The '?&?' on page 311 looks different from the '?&"' on page 310.

Note from the Author or Editor:
The ampersand should be a literal in "to remember not to use ?&? for the first".

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 327
Table 7-1. Prototypes to emulate built-ins

In the following table entries "mysin" ne "mysyn":

sub mysin (_) mysyn $a
mysyn

Note from the Author or Editor:
Both instances of "mysyn" should read "mysin".

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 346
last paragraph

In the following sentence, I think it meant to say, "an indirect filehandle":

Anytime you have a variable that contains a filehandle instead of a bareword
handle, you have an indirect filehandles.

Note from the Author or Editor:
Change as noted.

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 346
3rd paragraph

"Although you can usually use typeglob and references to typeglobs interchangeably, there are a few places where you can?t."

The first "typeglob" should be in plural, too.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 13, 2012  Jun 15, 2012
Printed
Page 356
3rd paragraph

The text reading:

only applies to C<my> variables.

should read

only applies to C<my> (and C<state>) variables.

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
PDF
Page 357
last code block

print "Be ", red("careful"), "with that ", green("light"), "!!!";

s/"with/" with/

Note from the Author or Editor:
Change as noted.

jlaire  Apr 13, 2012  Jun 15, 2012
PDF
Page 358
1st paragraph example

In the following example, there is a semicolon (;) in front of "@_" that I don't think was intended:

@colors = qw(red blue green yellow orange purple violet);
for my $name (@colors) {
no strict "refs"; # Allow symbolic references
*$name = *{uc $name} = sub { "<FONT COLOR='$name'>;@_</FONT>" };
}

Note from the Author or Editor:
Change as noted.

Anonymous  Feb 28, 2012  Jun 15, 2012
PDF
Page 368
-2nd paragraph

"inside the print statement:"

It's "say" now.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 13, 2012  Jun 15, 2012
Printed
Page 396
2nd paragraph

The text reading:

Any variable not associated with C<my> is associated

should instead read

Any variable not associated with C<my> (or C<state>) is associated

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
PDF
Page 403
2nd paragraph

"Some modules offer additional functionality in its import list."

That should end with "in their import lists".

Note from the Author or Editor:
Change as noted.

jlaire  Apr 14, 2012  Jun 15, 2012
Printed
Page 404
penultimate line of code at bottom of page

The line that reads:

${ "${{class}::name}" }; # symbolic reference

has a spurious open brace, and should instead read

${ "${class}::name}" }; # symbolic reference

Tom Christiansen
 
Apr 03, 2012  Jun 15, 2012
PDF
Page 405
5th (?) paragraph

The following sentence appears to be missing something (perhaps a word like "building" or "creating" or "defining" or ...?):

Earlier, we said that there are two ways for a module: traditional or object-oriented.

Note from the Author or Editor:
Change "ways for a module" to "flavors of modules".

Anonymous  Feb 29, 2012  Jun 15, 2012
PDF
Page 410
footnote

"CPAN:DistnameInfo" needs another colon.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 14, 2012  Jun 15, 2012
PDF
Page 421
2nd paragraph

I think you meant, "Notice the lack of a comma ...":

Notice the lack of a semicolon after the class name or instance:

Note from the Author or Editor:
Change as noted.

Anonymous  Feb 29, 2012  Jun 15, 2012
PDF
Page 429
3rd code block

package Horse;
use base qw(Critter).

The dot at the end of the second line should be a semicolon.

Note from the Author or Editor:
Change as noted.

jlaire  Apr 15, 2012  Jun 15, 2012
PDF
Page 432
1st and 2nd paragraph

I think you meant perl traverses @ISA array to find the right method, not @INC.

Note from the Author or Editor:
Change as noted

Anonymous  Oct 31, 2012  Jul 10, 2015
Printed
Page 435
1st paragraph

The text "has a similar problems" should read "has a similar problem".

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
PDF
Page 445
1st (?) paragraph

In this sub, $invocant is used once instead of $self:

sub AUTOLOAD {
my $self = shift;
# only handle instance methods, not class methods
croak "$self not an object" unless ref($invocant);
my $name = our $AUTOLOAD;
return if $name =~ /::DESTROY$/;
unless (exists $self?>{$name}) {
croak "Can't access '$name' field in $self";
}
if (@_) { return $self?>{$name} = shift }
else { return $self?>{$name} }
}

Note from the Author or Editor:
Change $invocant to $self.

Anonymous  Mar 01, 2012  Jun 15, 2012
Printed
Page 447
last paragraph

The spurious ">" after Bombadil should be deleted.

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
Printed
Page 467
2nd/3rd-to-last paragraph

There is a spurious paragraph break after "the result with make".

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
PDF
Page 483
2nd paragraph

(Sorry for the formatting loss.) As shown, that example would instead print:

101 Red
102 Green
103 Blue

Here?s a simple Tie::Counter class, inspired by the CPAN module of the same
name. Variables tied to this class increment themselves by 1 every time they?re
used. For example:
tie my $counter, "Tie::Counter", 100;
@array = qw /Red Green Blue/;
for my $color (@array) { # Prints:
print " $counter $color\n"; # 100 Red
} # 101 Green
# 102 Blue
The constructor takes as an optional extra argument the first value of the counter,
which defaults to 0. Assigning to the counter will set a new value. Here?s the class:
package Tie::Counter;
sub FETCH { ++ ${ $_[0] } }
sub STORE { ${ $_[0] } = $_[1] }
sub TIESCALAR {
my ($class, $value) = @_;
$value = 0 unless defined $value;
bless \$value => $class;
}
1; # if in module
See how small that is? It doesn?t take much code to put together a class like this.

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 01, 2012  Jun 15, 2012
Printed
Page 511
5th line

This line:
$x = tie $fred, "Remember", "camel.log";
Should be:
tie $fred, "Remember", "camel.log";

Otherwise, the explanation doesn't make sense.

Note from the Author or Editor:
This is not an error, but there is a different error.

Change line to this:

my $x = tie $fred, "Remember", "camel.log";

Make the same change to the last code example on that page.

Arnold Cross  May 25, 2019 
Printed
Page 511
middle of page

This line:
print { $self->{FH} } $handle $message, "\n";
Should be:
print { $self->{FH} } $message, "\n";

Two indirect objects won't work, unless there's something I don't understand. (I didn't test it, but I'm pretty sure about this.) Also, $handle is out of scope.

Note from the Author or Editor:
Change line to:

print { $self–>{FH} } $message, "\n";

Arnold Cross  May 25, 2019 
Printed
Page 529
middle of page

The following sentence is not grammatically correct. (Actually, it is grammatically correct, but it does not mean what it is intended to mean.)

= = = = =
If you really want the new program to gain access to a filehandle other than these three, you can, but you have to do one of two things.
= = = = =

The implied main verb to the modal "can" needs to have antecedent basis with the same subject. (I can't find this rule stated on the grammar websites, but I was taught well enough in grade school that I know it to be true.)

Any one of the following three corrections would fix the sentence.

1) ... other than these three, you can do this, but you have to do one ...

2) If you really want to make the new program gain access to a filehandle other than ...

3) ... other than these three, it can, but you have to do ...

As written, the sentence means: "You can want the new program to gain access, if you do one of two things."

Note from the Author or Editor:
Change the sentence to:

"To access to a filehandle other than these three, you have to do one of two things."

Arnold Cross  Jun 17, 2019 
PDF
Page 547
2nd paragraph

I may be missing something here but did the following mean "$socket" instead of "Server"?

shutdown(Server, 1); # Socket::SHUT_WR constant in v5.6

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 05, 2012  Jun 15, 2012
PDF
Page 550
3rd paragraph

Not technically wrong, but "\015\12" usually appears as "\015\012":

One additional consideration when writing Internet programs: many protocols
specify that the line terminator should be CRLF, which can be specified various
ways: "\r\n",11 "\015\12", or "\xd\xa", or even chr(13).chr(10). Many Internet
programs will in fact accept a bare "\012" as a line terminator, but that?s because
Internet programs usually try to be liberal in what they accept and strict in what
they emit. (Now if only we could get people to do the same?)

Note from the Author or Editor:
Change "\015\12" to "\015\012", as noted

Anonymous  Mar 12, 2012  Jun 15, 2012
Printed
Page 581
2nd paragraph

"Any value 0400 or above 0777 makes Perl slurp in whole files at once, but, by convention, the value 0777 is normally used for this."

Should be:

"Any value 0400 or above makes Perl slurp in whole files at once, but, by convention, the value 0777 is normally used for this."


Note from the Author or Editor:
Change as noted

Donald Canton  Oct 11, 2013  Jul 10, 2015
Printed
Page 589
2nd- and 3rd-to-last paragraphs

There are two instances of curly quotes following -M that should be straight quotes.

Tom Christiansen
 
Apr 02, 2012  Jun 15, 2012
PDF
Page 599
section on ":raw"

Instead of "Other layers that5 would affect" it should read "Other layers that would affect".

Note from the Author or Editor:
Change as noted

JoHa000  Dec 06, 2012  Jul 10, 2015
PDF
Page 619
4th paragraph

I think you meant "LineInfo=db.out":

If your init file contains:
parse_options("NonStop=1 LineInfo=tperl.out AutoTrace");
then your program will run without human intervention, putting trace information
into the file db.out. (If you interrupt it, you?d better reset LineInfo to /dev/
tty if you expect to see anything.)

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 08, 2012  Jun 15, 2012
PDF
Page 619
last paragraph

(Not really sure if this is a mistake.) This sentence is different from the one below it from perldoc:

The new method should inspect an argument
containing the value of $ENV{PERLDB_NOTTY} at startup, or /tmp/
perldbtty$$ otherwise.

The new method should inspect an argument containing the value of $ENV{PERLDB_NOTTY} at startup, or "$ENV{HOME}/.perldbtty$$" otherwise.

-- http://perldoc.perl.org/perldebug.html

Note from the Author or Editor:
The path should be "$ENV{HOME}/.perldbtty$$", with straight quotes inside the literal.

Anonymous  Mar 08, 2012  Jun 15, 2012
PDF
Page 622
6th (?) paragraph

1) "current_file" broken at line end,
2) One has ":::" and the other has "::":

The debugger also maintains magical internal variables, such as @DB::dbline and
%DB::dbline, which are aliases for @{":::_<current_file"} %{"::_<cur
rent_file"}.

Note from the Author or Editor:
The triple colon should be a double colon.

Nothing to be done about the linebreak in the middle of the literal, though.

Anonymous  Mar 08, 2012  Jun 15, 2012
PDF
Page 641
2nd paragraph

I think you meant "is a sophisticated tool" or "is a sophisticated set of tools":

Dist::Zilla
Dist::Zilla is a sophisticated tools that does much more than merely create the
initial distribution.

Note from the Author or Editor:
Change "tools" to "tool"

Anonymous  Mar 12, 2012  Jun 15, 2012
PDF
Page 681
7th (?) paragraph

I think you meant "assign the first line to $foo[0]":

Sometimes
this doesn?t make any difference, as in:
print "the answer is @foo[0]\n";
but it makes a big difference for things like:
@foo[0] = <STDIN>;
which will slurp up all the rest of STDIN, assign the first line to $foo[1], and
discard everything else.

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 12, 2012  Jun 15, 2012
PDF
Page 682
3rd paragraph

Did you mean "Encodings" because of "They"?

Encoding cannot be guessed. They
must be specified.

Note from the Author or Editor:
I'd rewrite this as "You cannot guess an encoding; you have to specify it."

Anonymous  Mar 12, 2012  Jun 15, 2012
PDF
Page 697
15th (?) paragraph

I can't seem to find File::Mmap, e.g.,

https://metacpan.org/search?q=file%3A%3Ammap
http://search.cpan.org/search?query=file%3A%3Ammap


Use File::Mmap to read files if you don?t need to modify the data (and sometimes
even if you do).

Note from the Author or Editor:
Change "File::Mmap" to "File::Map"

Anonymous  Mar 12, 2012  Jun 15, 2012
PDF
Page 713
footnote

"expat" appears to be a link, but doesn't go anywhere:

3. Actually, XML::Parser is just a fancy wrapper around James Clark?s expat XML parser.

Note from the Author or Editor:
The link should go to http://expat.sourceforge.net/

Anonymous  Mar 12, 2012  Jun 15, 2012
PDF
Page 740
1st paragraph

1) Granted that it depends on the pod translator, I still expected "touch -t" to appear in bold in this example.
2) Here and in many other places, both in the text and in examples, the hyphen appears as "?". Granted "?" B<looks> like an ascii hyphen, but if it's supposed to B<be> one, then it should be one. IMO. :?)

Note that pod sequences do nest. That means you can write ?The I<Santa
MarE<iacute>a> left port already? to produce ?The Santa Mar?a left port already?,
or ?B<touch> S<B<?t> I<time>> I<file>? to produce ?touch ?t time file?,
and expect this to work properly.

Note from the Author or Editor:
The "touch" and the "-t" should be rendered in bold, but are currently italic.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 740
last but four line

The example for pod2html should make use of pod2html, not pod2man.

On CPAN there is more than one pod2html, on METACPAN the best-rated one is Tom Christiansen's one: https://metacpan.org/module/pod2html .

Using that pod2html the line in the book should read like this:

% pod2html --infile=File.pm --outfile=tmppage.html

Note from the Author or Editor:
Change as noted

Jochen Hayek  Nov 20, 2012  Jul 10, 2015
PDF
Page 742
footnote

"Perl Power Tools" looks like a link, but it doesn't go anywhere:

3. And if you don?t, get the Perl Power Tools version from CPAN.

Note from the Author or Editor:
The link should be to https://www.metacpan.org/release/ppt/

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 744
last paragraph and footnote

The footnote says, "There has to be a space between the ?M and the name of the class." That's apparently not so, and the example exemplifies that.

By the way, there are no hyphens in this text. I promise not to mention it again.

You could write your own version of pod2text that loads a file and invokes your
subclass, but perldoc will load an alternate formatting class with the ?M switch:5
% perldoc ?MLocal::MyText some_pod.pod
5. This is not the same ?M switch for perl. There has to be a space between the ?M and the name of the class.
Sadly, perldoc does not warn you about these sorts of problems if you get it wrong.

Note from the Author or Editor:
Delete footnote 5 at the bottom of 744 altogether, as it no longer applies.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 758
6th paragraph

This link goes to this address:

http://www.stackoverflow.con/

Stackoverflow
Stackoverflow is a question-and-answer site for general programming. Even
though it is not dedicated to Perl, there are several Perl experts who frequent
the site and answer questions.

Note from the Author or Editor:
Change "con" to "com" in the domain name.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 766
1st paragraphish

Missing "$":

$^S (EXCEPTIONS_BEING_CAUGHT)

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 767
last paragraph

I may be making a stretch, but I don't think you meant, "each variable description in Table 25-1", because there aren't any variable descriptions in that table:

So that we don?t have to keep repeating ourselves, each variable description in
Table 25-1 starts with one or more of these annotations.

Note from the Author or Editor:
Delete "in Table 25.1"

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 781
2nd paragraph

This variable description is lacking an annotation, e.g., "[DYN]":

$^N The text matched by the used group most-recently closed (i.e., the group
with the rightmost closing parenthesis) of the last successful search pattern.

Note from the Author or Editor:
Prefix paragraph with "[DYN, RO]".

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 782
last paragraph (and cont. on next page)

This variable description looks odd, as though there are two different versions of the description (each beginning with an "[ALL]"):

%! [ALL] Each element of %! has a true value only if $! is set to that value. For
example, $!{ENOENT} is true if and only if the current value of $! is ENOENT;
that is, if the most recent error was ?No such file or directory? (or its moral
equivalent: not all operating systems, and certainly not all languages, give
that exact error). To check for whether a particular key is meaningful on
your system, use exists $!{SOMEKEY}; for a list of legal keys, use keys %!. See
the documentation for the Errno module for more information, and see also
$! above.
This variable was added in v5.005.
[ALL] This hash is defined only if you?ve loaded the standard Errno module.
Once you?ve done this, you can subscript into %! using a particular error
string, and its value is true only if that?s the current error. For example, $!

[next page]

{ENOENT} is true only if the C errno variable is currently set to the C
#define value, ENOENT. This is convenient for accessing vendor-specific symbols.

Note from the Author or Editor:
Delete the second of the two paragraphs beginning with [ALL].

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 783
2nd paragraph

I think you meant "$," (not "$/"):

$OUTPUT_FIELD_SEPARATOR
$/ [ALL] The output field separator (terminator, actually) for print. Ordinarily,
print simply prints out the list elements you specify without anything between
them. Set this variable as you would set awk?s OFS variable to specify
what is printed between fields. (Mnemonic: what is printed when there is a
?,? in your print statement.)

Note from the Author or Editor:
Change the "$/" variable to read "$," ? also, delete the "(terminator, actually)" phrase.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 784
3rd-ish paragraph

Huh? :-)

$ perl ?E 'say $^V 5.10.1'
1

Note from the Author or Editor:
That is missing a comparator, and should be

$ perl -E 'say $^V > 5.10.1'

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 785
4th (?) paragraph

This variable description is lacking an annotation, e.g., "[DYN,RO]":

${^PREMATCH}
This is just like $` ($PREMATCH) except that it does not incur the performance
penalty associated with that variable, and it is only guaranteed to contain a
defined value when the pattern was compiled or executed with the /p modifier.

Note from the Author or Editor:
Change as noted.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 796
Table 26-5

... q/, and nonzero binary with "0b"/ ... ?

# Prefix nonzero octal with ?0?, nonzero hex with ?0x?

Note from the Author or Editor:
Add "nonzero binary with 0b" after "nonzero hex with 0x" in the fifth row in the table.

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 797
8th paragraph

From the department of redundancy department:

This also allows you to reuse arguments, too:
printf '%2$d %1$d %2$d', 12, 34; # "34 12 34"

Note from the Author or Editor:
Remove ", too"

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 807
3rd paragraph

I can't seem to find a verb:

The < and > for endianness on the specifier on d, D, f, F, i, I, j, J, l, L, p, P, q, Q,
s, and S.

Note from the Author or Editor:
Change to "The < and > indicate the endianness for the specifiers d, ..."

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 809
4th paragraph

More additional extra redundancy:

The unpack function is also useful for plain text data, too, not just binary data.

Note from the Author or Editor:
Remove the ", too"

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 817
3rd paragraph

Um, well, uh, those don't even look like quotes (I didn't mention the hyphen). :-)

Here?s another strategy: open a pipe to yourself using open(MESELF, ?|??) (see the
open entry in Chapter 27), and always write to MESELF instead of STDOUT.

Note from the Author or Editor:
The curly quotes should be straight quotes

Anonymous  Mar 13, 2012  Jun 15, 2012
PDF
Page 866
4th paragraph

Are those last two paragraph repeats of the first two?

If you fork without ever waiting on your children, you will accumulate zombies
(exited processes whose parents haven?t waited on them yet). On some systems,
you can avoid this by setting $SIG{CHLD} to ?IGNORE?; on most, you must wait for
your moribund children. See ?wait? in this chapter for examples of doing this,
or see the section ?Signals? on page 518 in Chapter 15 for more on SIGCHLD.

If a forked child inherits system file descriptors like STDIN and STDOUT that are
connected to a remote pipe or socket, you may have to reopen these in the child

[Perl Functions in Alphabetical Order | 865]

to /dev/null. That?s because even when the parent process exits, the child will live
on with its copies of those filehandles. The remote server (such as, say, a CGI
script or a background job launched from a remote shell) will appear to hang
because it?s still waiting for all copies to be closed. Reopening the system filehandles
to something else fixes this.

[...]

If you fork without ever waiting on your children, you will accumulate zombies.
On some systems, you can avoid this by setting $SIG{CHLD} to ?IGNORE?. See also
Chapter 15 for more examples of forking and reaping moribund children.

Note that if your forked child inherits system file descriptors like STDIN and
STDOUT that are actually connected by a pipe or socket, then the remote server
(such as, say, a CGI script or a backgrounded job launched from a remote shell)
won?t think you?re done, even if you exit the parent process. You should reopen
those to /dev/null if this is an issue.

Note from the Author or Editor:
Delete the last two paragraphs of the fork section: they're duplicates.

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 868
2nd paragraph

Do I really care? No, but I thought you might -- it just jumped out at me:

it's ne it?s

Note from the Author or Editor:
There's a non-curly quote in the first line of the second paragraph

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 871
2nd paragraph

Did you mean "The Socket module has a ...":

The Socket module is a gethostinfo function that works for addresses in all common
forms, including IPv6.

Note from the Author or Editor:
Change as noted

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 875
2nd paragraph

Did you mean "# 0 1 2":

This function translates a protocol number to its corresponding name. The return
value in list context is:
# 1 2 3
($name, $aliases, $protocol_number) = getprotobynumber(6);

Note from the Author or Editor:
Change as noted

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 875
4th paragraph

Did you mean "# 0 1 2":

These functions iterate through the /etc/protocols file. In list context, the return
value from getprotoent is:
# 1 2 3
($name, $aliases, $protocol_number) = getprotoent();

Note from the Author or Editor:
It should be # 0 1 2 in both cases on this page

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 880
6th paragraph

Small nit: the "0" in "month 0" is different than the one in "day 0" (this is also true on page 893, 4th paragraph):

In particular, this means that $mon has
the range 0..11, with January as month 0, and $wday has the range 0..6, with
Sunday as day 0.

Note from the Author or Editor:
The zero in "month 0" should be in the code font

Anonymous  Mar 22, 2012  Jun 15, 2012
PDF
Page 889
4th paragraph

You mention 'use feature "fc"' in the 'lc' section (and the one for 'uc'), but not in the one for 'fc':

Instead, use the fc
(foldcase) function, either from the CPAN Unicode::CaseFold module, or via use
feature "fc" in v5.16 or later.

Note from the Author or Editor:
Change the fc function on page 860 from reading simply "New to v5.16" to reading "New to v5.16 where it is enabled with C<use feature "fc">," ? and of course set the C<> as a literal.

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 889
last paragraph

Did you mean "L<perlfunc>":

See
the perllocale, perlunicode, and LIperlfunc> manpages for the most recent results.

Note from the Author or Editor:
The LIperlfunc> should be perlfunc with a link to http://perldoc.perl.org/perlfunc.html

Anonymous  Mar 20, 2012  Jun 15, 2012
PDF
Page 891
2nd paragraph

Need space after "This":

Thisfunction tells the system that you?re going to be accepting
connections on this
SOCKET and that the system can queue the number of waiting connections specified
by QUEUESIZE.

Anonymous  Mar 22, 2012  Jun 15, 2012
PDF
Page 893
5th paragraph

Did you mean something like this:

$thisday = qw(Sun Mon Tue Wed Thu Fri Sat)[(localtime)[6]];

Don't get me wrong; I'm not the code police. It's just that it's been so long since I programmed with bare words, this looked like a syntax error:

$thisday = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[(localtime)[6]];

Note from the Author or Editor:
Quote each word in the list for strict complacence.

Anonymous  Mar 22, 2012  Jun 15, 2012
PDF
Page 896
4th paragraph

The "use" in "use IPC::SysV" is different than where that phrase is used elsewhere (e.g., further down that page):

This function calls the System V IPC msgget(2) syscall. See msgget(2)
for details.
The function returns the message queue ID, or undef if there is an error. Before
calling, you should use IPC::SysV.

Note from the Author or Editor:
Set the "use" as a literal, like the other one.

Anonymous  Mar 22, 2012  Jun 15, 2012
PDF
Page 901
3rd paragraph

I think you mean "$dec_perms" instead of "$perms":

$dec_perms = (stat("filename"))[2] & 07777;
$oct_perm_str = sprintf "%o", $perms;

Note from the Author or Editor:
Change $perms to $dec_perms

Anonymous  Mar 22, 2012  Jun 15, 2012
Printed
Page 908
3rd paragraph

Replace $AUTOFLUSH with $OUTPUT_AUTOFLUSH

Note from the Author or Editor:
Change as noted

Anonymous  Jun 05, 2013  Jul 10, 2015
Printed
Page 911
ord function paragraph

"To find the codepoint for a character gives it name as a string, use the charnames::vianame functions from the charnames pragma."

should maybe be something like:

"To find the codepoint for a character that gives its name as a string, use the charnames::vianame function from the charnames pragma."

Note from the Author or Editor:
It should read: "given its name as a string", and "functions" should be changed to "function".

aphilipp  Apr 03, 2012  Jun 15, 2012
Page 923
code block under 1st paragraph

This code block will never print any file names:

opendir(THATDIR, $path) || die "can't opendir $path: $!";
@dotfiles = grep { /^\./ && –f } map { "$path/$_" } readdir(THATDIR);
closedir THATDIR;

The reason being, after tacking "$path" to the left end, none of the names will begin with a dot. To make that work, you'd have to split the grep:

opendir(THATDIR, $path) || die "can't opendir $path: $!";
@dotfiles = grep { –f } map { "$path/$_" } grep { /^\./ } readdir(THATDIR);
closedir THATDIR;

Note from the Author or Editor:
Change as noted

Robbie Hatley  Mar 20, 2023 
Printed
Page 932
'say' function description (5th & last para body text)

The text states that the 'say' keyword:
"...is available only when the "say" feature is enabled; see the section "Terms and List Operators (Leftward)" on page 97 in Chapter 3.

This is an incorrect citation; this section is not relevant to enabling the "say" feature and does not refer to it at all.

The correct citation would be to the section on the feature pragma on page 1017.

Note from the Author or Editor:
Change as noted

William Perlist  Jun 14, 2012  Jul 10, 2015
PDF
Page 933
3rd paragraph

The sentence says, "print" but the example says, "say":

Since a print function is a LIST operator, you have to say:
say "Length is ", scalar(@ARRAY);

Note from the Author or Editor:
Change to "Since a say function is a LIST operator"

Anonymous  Mar 22, 2012  Jun 15, 2012
PDF
Page 937
last paragraph

Did you mean "effects"? (Please don't hit me.)

(A timeout of 0 affects a poll.)

Note from the Author or Editor:
Change "affects" back to "effects" per Camel3.

Anonymous  Mar 29, 2012  Jun 15, 2012
PDF
Page 938
last paragraph

s/\.systems/systems/;

One should probably not (attempt to) mix buffered I/O (like read or <HANDLE>)
with select, except as permitted by POSIX, and even then only on truly POSIX
.systems. Use sysread instead

Note from the Author or Editor:
The period at the front of the line should be its end.

Anonymous  Mar 29, 2012  Jun 15, 2012
PDF
Page 951
last paragraph

The third "PATTERN" isn't italicized:

split /PATTERN/, EXPR, LIMIT
split /PATTERN/, EXPR
split /PATTERN/
split

Note from the Author or Editor:
Change as noted

Anonymous  Mar 29, 2012  Jun 15, 2012
PDF
Page 983
1st paragraph

Does that have one too many $then's?

utime($then, $then, $then, *SOME_HANDLE);

Note from the Author or Editor:
Delete one of the "$then, " arguments.

Anonymous  Apr 09, 2012  Jun 15, 2012
PDF
Page 1026
section for "parent"

In this section, "@INC" is referred to where I think you meant "@ISA":

parent
use parent qw(Mother Father);
The parent pragma supersedes the base pragma. It loads modules and sets up
inheritance relationships without the %FIELDS hash magic, and it provides a way
to set up inheritance without loading files.
The following example is equivalent to loading both parent modules and adding
them to @INC without declaring @INC explicitly:
BEGIN {
require Mother;
require Father;
push @ISA, qw(Mother Father);
}
This assumes each parent module lives in its own file. If the parent classes do not live
in separate files, perhaps because you?ve defined them in the same file or already
loaded them from a file as part of another class, you can use the ?norequire option
to merely set up the inheritance relationship:
use parent qw(?norequire Mother Father);
This is equivalent to adding those classes to @INC:
BEGIN {
push @ISA, qw(Mother Father);
}

Note from the Author or Editor:
That final @INC under "parent" should be @ISA

Anonymous  Mar 05, 2012  Jun 15, 2012
Printed
Page 1063
The gloss "lexical variable"

Change "declared by C<my>" to "declared by C<my> or C<state>".

Tom Christiansen
 
Apr 01, 2012  Jun 15, 2012
Printed
Page 1099
5th line from the bottom of the first column

The index references a unknown comparison operator: "cpm". Should have been "cmp".

Note from the Author or Editor:
Change as noted

Jean Forget  Oct 21, 2013  Jul 10, 2015
PDF
Page 1130
entire page

The index contains many link errors. Some examples:
p. 1130, "last assingments, 83" does not link at all;
p. 1130, last entry "zombie processes, 521, 1081" erroneously links to p. 197 and 218, respectively.
Also, clicking just slightly to the right of "521" *also* links to 218. Clickable areas are located slightly left of where they should be.
Tested with both Adobe Reader and Foxit Reader.

Alex Kok  Jun 11, 2013  Dec 13, 2013
Printed
Page 1130
First entry for letter X

Change :
cdebugger ommand
to
debugger command.

Also, change
underPrint
to
undefPrint

Note from the Author or Editor:
Change as noted

Jean Forget  Oct 23, 2013  Jul 10, 2015
PDF
Page 1172
middle

The page numbers for the "utf8 pragma" are not linked to the occurrences within the text. This is also true for many, many other index entries.

Your Perl Cookbook ebook is much better in that respect.

Note from the Author or Editor:
The index needs work

JoHa000  Oct 31, 2012