Book Reviews

The following book reviews are the copyright of their respective authors and no part should be reproduced without the express permission of the author. Publishers and Authors of the books reviewed may reproduce the whole or extracts of a review for their book. To request copyright permission please email webmaster@birmingham.pm.org.

All the reviews herein are the opinions of the reviewer and are not necessarily the views of Birmingham Perl Mongers and its members. If you feel a review or comment has been made in error, please contact webmaster@birmingham.pm.org to rectify the situation.

Perl Books

Static Link: http://birmingham.pm.org/reviews/56

 
Mastering Perl
Title:Mastering Perl
Author(s):brian d foy
ISBN:0596527241
Publisher:O'Reilly Media
Reviewer:Brian McCauley

This book seeks to be a sequel to the highly regarded “Learning Perl” and “Intermediate Perl”. Unfortunately it doesn't live up to this aim. I did set out to study the book in some detail to write a detailed review, but before long I found that I had switched to proof-reading mode writing and was writing pre-publication list of corrections. But this book has already been published. A book of this type this cannot simply afford to contain such a significant density of errors.

The narrative style of the book will grate on some people and in particular brian's tendency to self-congratulation could be said to be irritating. At least that's what I've been told, as it happens, I'm not one of those people who find this a problem.

The ordering of topics is somewhat erratic. Admittedly it is not possible to always maintain a logical progression of subject matter but why, for example, does chapter 5 go from profiling Perl code to profiling database accesses then back to Perl profiling?

There are a number of places where the narrative is factually incorrect or at least misleading.

Good code examples are central to any programming language book. There are a number of problems with the code examples in this book.

  • Some contain idiosyncrasies which distract from illustrating the point.
  • Some contain completely redundant code which distracts from illustrating the point.
  • Some simply fail to illustrate the point they are intended to.
  • Some do llustrate very interesting facts about Perl, but the associated narrative does not pick up on these.
  • Some contain errors that would make them produce the wrong output for valid input different from that used in the example.
  • Some contain errors that would make them produce the wrong output for the input that is used in the example.
  • Some contain errors that would stop them from compiling altogether.

Finally, and in my view most damningly, there are also what I would consider conspicuous omissions, where the book regurgitates the same shallow explainations that we see in numerous other books and even the standard Perl manuals, without taking that extra step one would hope to see in a book targeted at those seeking a mastery of the language. For example

  • The \G regex assertion – there are no examples showing its use other than at the beginning of a pattern.
  • The (?=...) assertion – there is no mention that you can capture within (?=...).
  • Section on hash keys untainting misses the point. It labours the point that one should not deliberately use this as an untainting mechanism rather than pointing out that this is something one could easily do unwittingly.
  • Section on tainting in general does not mention that symbolic references are not checked for taint.
  • Explanation of local($n) in the section on symbol tables and typeglobs is the usual simplistic explanation not the pedantic explanation that you need if you are to become a master of the typeglob.

In conclusion, this book is a disappointment and not up to the standard we have come to expect from O'Reilly. Save your money, don't buy this book.

What now follows are my proofreader's notes of a few chapters:

Chapter 2

Page 9: States that @+ and @- will always be of the same length. This is not true $#+ is the number of capturing parentheses in the pattern whereas $=- is the index of the last capture involved in the match.

Page 17: A footnote where the @{[...]} construct is used to interpolate a function call reads “this is the same trick I use to interpolate function calls”. Duh?

Page 18: Example contains unreachable code after last.

Page 18/19: foreach loop is named MATCH but next does not use the label. Two variables declared and never used.

Page 19: Narrative implies that $regex=qr/[a-z]/; /$regex/i; would match case insensitively. This is, of course, not true.

Page 20: Lookahead expressions are not properly anchored leading to combinatorial explosion. Narrative and diagrams misuse the term “anchored” and are likely to leave a reader who started with a partial understanding worse off than they started.

Page 25: Transposition of characters in code example $money=$'1234.5678' (would not compile). “Solution” given to the “comify before the decimal point problem” is not actually a solution – it would fail for '123.456789'.

Page 28: The syntax for named character classes is /[[:alpha:]]/ not /[:alpha:]/.

Chapter 3

Page 33/34: Very long-winded example that starts “If I can fool you into thinking this program is perl...”. The whole example is moot. If an attacker can fool you into running his code then it's game over already.

Page 38: Spurious /g qualifier on pattern match.

Page 40: Narrative says “turn off regular expression tainting” when it means “turn off regular expression untainting” which, confusingly is done by switching on the pragma “re taint”. This is confusing enough without the book compounding the issue.

Page 41: States the value of a?b:c is untainted so long as neither b nor c is tainted. This is true but misleading – the value of a?b:c is tainted if the chosen one of b or c is tainted.

Chapter 4

Page 49/50: Example using Carp::carp should in fact be using Carp::cluck. It only works as described because when Carp::carp is called in a context where doing what it's supposed to do is impossible it falls back to behaving as Carp::cluck. In any non-trivial situation (where the call stack contains multiple packages) Carp::carp will behave as intended and not as described in the book.

Page 51: As above, Carp::croak should be Carp::confess.

Page 52: Talks about confess and cluck as being different from croak and carp even though the preceding examples (using croak and carp) were, in effect, actually examples of using confess and cluck.

Page 54: Description of the purpose of the expression defined($overload::VERSION)? overload::StrVal($arg) : "$arg" in Data::Dumper is completely inverted. The purpose of this code is to prevent modules that use overloading from stringifying $arg in any way other than the normal way. This is not just confused writing as the next paragraph goes on to compound the fallacy.

Page 55: Code example needlessly uses a BEGIN block and GLOB assignment to redefine a subroutine where a simple subroutine definition would have done perfectly well.

Page 60: -D should read -d

Page 126: local($n) does not (usually) move the current value of $n out of the way temporarily. It leaves the current value were it is makes *n{SCALAR} point temporarily to a different scalar value. The distinction is subtle and in many contexts simplistic explanation is sufficient. The chapter dealing with typeglobs and the symbol table, in a book aimed at those seeking mastery of Perl, is most certainly not such a context.

Page 128: States the symbol tables are not real Perl hashes but does not mention how they actually differ from normal hashes. The difference is in fact very subtle and probably should be explained or at least mentioned.

Page 130: The phase “variables I've defined” is probably misleading – indeed it seems unlikely the author actually knew what he meant. From context he means variables that exist in the symbol table. However this is not what the code example which follows tests by using the defined() function.

Page 130/131: The illustration of the behaviour of package variables is flawed. In particular both the code example and the narrative fail to illustrate the point that variables are entered into the symbol table at compile time. The example code does illustrate that symbol table entries become bound to code at compile-time and remain bound even if you subsequently delete the symbol table entry. Unfortunately the narrative fails to pick up on this important and far from intuitive fact.

Page 131: It is confusing to use the word “variable” to describe the NAME and PACKAGE slots in a GLOB.

Page 132: Colon at end of first paragraph implies what follows is an illustration of what was just described. It's not.

Page 132: Code example shows the assignment of a GLOB (not, as is more common, a GLOBref) into a scalar variable but does explain what's going on when you do this. It's far from trivial and understanding it is another of those things that would set a Perl master apart from the unwashed masses. Uses local() for no valid reason.

Page 134: Explains what Exporter does but misses the point about how it is that simply assigning to a typeglob gets around the need to declare variables (the import flag).

Page 134: States that open() autovivifies filehandles as IOrefs. But actually it autovivifes them as GLOBrefs. Goes on to state that local(*FH)=shift in a subroutine that is passed a filehandle argument will replace only *FH{IO}. This is true if one actually passes the filehandle as a IOref but as I just mentioned one very rarely uses IOrefs as such.

Page 136: Example of using GLOB assignment is totally artificial as it's a situation where there's no reason why one shouldn't simply use references directly.

Page 139: Code example uses use vars for no apparent reason.

Page 139: The anonymous subroutine for division has both an eval and a test that the denominator is true so will return 'NaN' for a denominator of 0 but undef for a denominator of 'NaN'.

Page 140: The anonymous subroutine for division has mysteriously changed and this time it will return 'NaN' for a numerator of 0. So is even more broken than it was on the previous page.

Page 140: Narrative states that the following example uses List::Util::max but it doesn't.