[8139] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 1758 Volume: 8

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Jan 29 03:07:14 1998

Date: Thu, 29 Jan 98 00:02:51 -0800
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Thu, 29 Jan 1998     Volume: 8 Number: 1758

Today's topics:
        TYP21D (was: substitute...) <tchrist@mox.perl.com>
        URL problems in HTTP::Request call (stewart samuel bushman)
        Digest Administrivia (Last modified: 8 Mar 97) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: 28 Jan 1998 17:04:08 GMT
From: Tom Christiansen <tchrist@mox.perl.com>
Subject: TYP21D (was: substitute...)
Message-Id: <6anoe8$9mv$1@csnews.cs.colorado.edu>

 [courtesy cc of this posting sent to cited author via email]

In comp.lang.perl.misc, Duane Lecky <dlecky@uvic.ca> writes:
:I find that when I am learning I language I like to use books designed 
:for teaching.  My reference book for Perl was initially "Teach Yourself 
:Perl in 21 days" by David Till.  It was excellent.  Now I can use 
:reference materials like the Camel books.  Initially though, it is great 
:to have things like s/// well spelled out with examples and explanations 
:of how to use them.

The following is a text copy of a review by Tom Grydeland, not by me.
It can be found on http://www.eiscat.uit.no/people/tom/TYP21D.html if
you prefer that format.

--tom

   * A critical review of teach yourself PERL 5 in 21 days, 2/e
        o by Tom Grydeland
   * Introduction
        o General remarks
        o Typography
        o Finally,
   * The week
        o Features new to this book
        o Introduction
        o Day 1 Getting Started
        o Day 2 Basic Operators and Control Flow
        o Day 3 Understanding Scalar Values
        o Day 4 More Operators
        o Day 5 Lists and Array Variables
        o Day 6 Reading from and Writing to Files
        o Day 7 Pattern Matching
   * The Second Week
        o Day 8 More Control Structures
        o Day 9 Using Subroutines
        o Day 10 Associative Arrays
        o Day 11 Formatting Your Output
        o Day 12 Working with the File System
        o Day 13 Process, String and Mathematical Functions
   * The Third Week
        o Day 14 Scalar-Conversion and List-Manipulation Functions
        o Day 15 System Functions
        o Day 16 Command-Line Options
        o Day 17 System Variables
        o Day 18 References in Perl 5
        o Day 19 Object-Oriented programming in Perl
        o Day 20 Miscellaneous Features of Perl
        o Day 21 The Perl Debugger
   * Conclusions
   * References

  ------------------------------------------------------------------------

A critical review of teach yourself PERL 5 in 21 days, 2/e

by David Till (with two chapters by Kamran Husain)

  ------------------------------------------------------------------------

by Tom Grydeland

  ------------------------------------------------------------------------

Introduction

I've been programming perl for a couple of years, ever since my system
administrator recommended it over shell programming for tasks where C just
didn't seem the right tool. I've come to love it for its way of making
things simpler. With v.5, even the things that used to be tricky in perl
(multi-level data structures) have become simple, and with the module
system, code reuse is a reality.

I have read both editions of the camel book [4,5] and I've learned to
appreciate them as reference works and examples of working code, although
it's not always easy to find exactly what you're looking for in them (now
where were the -X file test operators hidden again?)

Then comes an 870+ pages volume which boasts on the cover: ``teach yourself
PERL 5 in 21 days''

  ------------------------------------------------------------------------

General remarks

This must be the most verbose perl I've ever seen written. It looks as if
the author really wants to use C instead, and avoids using everything that
makes perl worth using. It takes three times as much space as really
necessary to explain anything, and everything is explained three times;
first using the hardest way available, then ironing out some of the most
verbose, and finally something which vaguely resembles perl. (see the
example cited from p. 126 for what I mean.) Yes, TMTOWTDI, but this is
ridiculous.

What really bugs me about this, is that the presentation makes Perl look
like a language with lots and lots of misfeatures and useless constructs. If
this book was the only thing I'd ever read about Perl, I wouldn't see any
point in learning the language. Yes, Perl has its warts, but this book
presents it as all warts.

Every built-in function or operator is called a ``library function'',
something that the author can allow himself to do, since he never intends to
use the perl library anywhere in the book. (use isn't even mentioned in the
index, and I've only spotted it twice in the text (Day 17, last section,
Specifying System Variable Names as Words, which uses English; and Day 19,
the Cocoa example)).

The author completely fails to grasp the difference between the null string
"" and the undefined value. This leads to bad advices, difficult programming
(see Day 5 example) and, when the undefined value is finally introduced, the
following helpful rule of thumb (p. 493, the Note box):

`The general rule is: A function that returns the null string when an error
or exceptional condition occurs is usually really returning the undefined
value.'

Now, if that was actually used anywhere in the code! See also my comment to
the Tip box on p. 128.

In addition, it's riddled with errors, questions are answered incorrectly in
the Q&A sessions, solutions are presented as correct, even when the text
later states that they are wrong, and several of the Tip and Do/Don't boxes
contain style advice I'd shun.

The cover boasts that the book is Completely Updated and Revised!, but to me
it looks like the smallest rewrite that the author could get away with for a
new edition, sometimes presenting obsolete (v.4) solutions and presenting
the new way in a Note box as an afterthought. At least once, not even that.
(The presentation of q//, p. 723.) Many of the examples that could have
demonstrated the author's understanding of Perl has instead become examples
of exactly how little effort the author wanted to put into the making the
book a reliable source of information.

  ------------------------------------------------------------------------

Typography

On the plus side, the fonts used both for running text and program listings
are easy to read.

Unfortunately, the fixed width font has two critical shortcomings:

   * The single quote ' looks like a straight quote, and it is thus
     impossible to determine from a glance whether a single quote or a
     backtick was intended.

   * Instead of a minus character, a hyphen is used, which is hard on the
     eyes. In addition, it would appear that the typesetting system used
     will interpret consecutive dashes to an em-dash, sometimes actively
     exploited by the author, while other times leaving the text wrong. (See
     p. 595.)

  ------------------------------------------------------------------------

Finally,

I'm usually a forgiving reader. But when I read a technical book, especially
when it's ment for studying without the assistance of a teacher who can
guide you over the rough spots, one thing I demand is accuracy. The informal
parts can be as sloppy as they like (or left out altogether), but the
technical parts, the reference material, has to be 100% accurate (within the
typo devil's grace), or the book is 100% worthless.

This book is nowhere near 100% accurate. Several of the examples are so
wrong that even a moderately experienced programmer like myself could see
that they would never work with barely a sideways glance at the code.

I haven't even bothered worrying whether the code would be OK under -w or
use strict. There's far too much to comment on just getting the code to work
at all.

To give a preview of my conclusions: If this is the book I had when I
started to learn Perl, I'd never have learned Perl. Firstly, it gives the
(decidedly wrong) impression that things are difficult to do in perl, and
secondly, it gives the (also decidedly wrong) impression that there are so
many things in Perl that are dangerous to do that you might just as well do
it in C.

I have my own Do/Don't box to suggest for this book:

Do
     yourself a favour: Look somewhere else for your Perl information.
     http://www.perl.com is great, as is Programming Perl.

Don't
     waste your money and time on this book.

Since I'm seriously un-impressed by the book, I'm focusing on the things I
don't like. This will probably make it look a lot worse than it actually is.
Take this bias into account when you read this review.

  ------------------------------------------------------------------------

The week

  ------------------------------------------------------------------------

Features new to this book

Good point: I actually learned that -F was new in v.5.

Bad points:

Even before the title page, the inaccuracies come.

The page begins ``This edition of Teach Yourself Perl in 21 Days covers the
following features, which have been introduced in version 5 of Perl. ...''

The list contains (amongst others) the following items

   * The wantarray function enables you to ...

   * The dump function enables you to ...

both of which are definitely features of v. 4 or earlier.

  ------------------------------------------------------------------------

Introduction

Mostly OK. What you'll learn in 21 days includes a 2-page overview of the
three weeks ahead, the first third of which is immediately reproduced in
Where you're going in Week at a glance (sic) two pages later.

  ------------------------------------------------------------------------

Day 1 Getting Started

   * p. 3 `[Perl] was designed by Larry Wall [...] and is continually being
     updated and maintained by him.'

     I'm not sure the rest of the world would take the efforts of the Perl
     porters that lightly.

   * p. 5 Where do I get Perl? Instead of using the opportunity to introduce
     CPAN, he points everybody at prep.ai.mit.edu and tells them to get
     perl-5.001.tar.gz. Yes, other sites are mentioned over the next few
     pages, but CPAN is not.

   * pp. 9 - 12 gives a useful walk-through of the steps often needed to
     make a script run. This section I like. What I don't like, is this:

   * The Do/Don't box on p. 12 states

     `DON'T
          put anything else after /usr/local/bin/perl in the first line:

              #!/usr/local/bin/perl

          This line is a special comment line, and it is not treated like
          the others.'

     Yes, it's a ``special comment line'', but you might still use switches,
     and, in fact, this would be a perfect place to recommend always adding
     the -w switch to the #! line! so:

     DO
          put -w after /usr/local/bin/perl in the first line!

   * p. 15 Function invocation and Arguments `In Perl, [the arguments to a
     function are] supplied as a sequence of comma-separated items located
     between the parentheses of the function invocation'

     Yes, you can have parentheses around arguments. No, you don't have to
     have them. As an author, you're free to advise people to always use
     parentheses around the arguments. You're not, however, free to claim
     that these parentheses are required.

  ------------------------------------------------------------------------

Day 2 Basic Operators and Control Flow

   * p. 27 The chop Library Function (sic) doesn't mention that chop returns
     the character chopped.

   * p. 31 The if statement From the description, it would appear that the
     if statement, the if-else statement and the if-elsif-else statement are
     different statements.

     Also, by not introducing the BLOCK syntax element, it becomes necessary
     to point out that, unlike in C, the braces are necessary.

   * p. 35 the Warning box warns about confusing = and == with the example

         if ($number = 5) {
             print ("The number is five.\n");
         }

     which the -w flag would've warned him about in the first place.

   * p. 40 describes the if-elsif-else statement as

         if (expr_1) {
              statement_block_1
         } elsif (expr_2) {
              statement_block_2
         } elsif (expr_3) {
              statement_block_3
         ...
         } else {
              statement_block
         }

     Huh? do I need to have two elsifs if I want any? Isn't
     statement_block_3 terminated by braces? Is that a spurious close-brace
     before else or what is it?

     Yes, of course you'll get their meaning, but it's not accurate! Worse,
     with the position of the ..., it's wrong.

   * p. 44 Syntax description for while doesn't even mention that you can
     have a continue block. Not even with a forward reference to the page
     where he does. (p. 283)

     An example of what I'd call confusing by too much explaining is in the
     section ``Nesting Conditional Statements'' on the same page:

     `In Perl, you can nest any conditional statement inside another. For
     example, you can have a while statement inside another while statement,
     as follows:

     [example not included]

     Similarly, you can have an if statement inside another if statement, or
     you can have a while statement inside an if statement.'

     Does that mean I cannot have an if statement inside a while statement?
     I mean, he mentioned all the other combinations. What about an if-else
     statement? Can I put that inside a while statement or a while statement
     inside it? What about several levels of nesting?

     By going into too much unnecessary detail, the presentation has become
     erroneous, or at least unclear and confusing. This is typical of the
     book.

  ------------------------------------------------------------------------

Day 3 Understanding Scalar Values

   * p. 52 Integer Scalar Values `An integer scalar value consists of one or
     more digits, optionally preceded by a plus or minus sign and optionally
     containing underscores.'

     Seems our author doesn't know the difference between a value and its
     string representation, be it as input or as literals in the program.

   * p. 54 Floating-Point Scalar Values `As you have just seen, integers in
     Perl actually are represented as floating-point numbers. This means
     that an integer scalar value is actually a special kind of
     floating-point scalar value.'

     To paraphrase Tom C. in his review of Perl 5 Unleashed:

     `They don't understand that Perl sometimes stores things as integers,
     other times as doubles.'

   * p. 62, table 3.1 Escape sequences in strings Includes \v which is not,
     and never was, supported.

   * p. 65, the Warning box `Single-quoted strings can be spread over
     multiple lines. [...] This means that if you forget the closing ' for a
     string, the Perl interpreter (sic) is likely to get quite confused
     [...]'

     As if that didn't apply to double-quoted strings as well!

     Also, none of the alternate quoting mechanisms, q// and qq//, are
     touched upon or referred to.

   * p. 66, the Warning box `If a string contains characters that are not
     digits, the string is converted to 0 when used in an integer context
     (sic). [...] In cases like this, Perl does not tell you that anything
     has gone wrong, and your results might not be what you expect'

     First, "5hi" will be converted to 5, not zero (as the author's own
     example further down in the same box also illustrates). Second, there's
     no such thing as an ``integer context'' (unless you count use integer;
     as such). Third, -w will make perl warn you about non-numeric argument
     conversions!

     (I begin to understand why Larry Wall considers it a bug that -w isn't
     on by default.)

   * p. 66, Initial Values of Scalar Variables ``null string'' should have
     been undef

  ------------------------------------------------------------------------

Day 4 More Operators

Good thing: The book actually mentions

    $myval = $a || $b || $c;

and what it does. It doesn't use it anywhere, though.

   * p. 99 last para Says ``integers'' where he means ``numbers''. No, it's
     not a big deal, but it's unnecessary confusion.

  ------------------------------------------------------------------------

Day 5 Lists and Array Variables

Good thing: The book points out that a list and an array is not the same,
but that one can be assigned to the other.

Good thing: The book illustrates the array slice notation well.

   * p. 123, the Note box ``null string'' should have been undef

   * p. 126, Listing 5.3, list ranges This is a program to illustrate how
     the .. (list range) operator works. Instead of doing something which
     could use list ranges in a useful way, the program will simply print
     out all values between a user-supplied start and end of a range,
     inclusive.

     After reading in $start and $end, the program goes:

         @list = ($start..$end);
         $count = 0;
         print ("Here is the list:\n");
         while ($list[$count] != 0 || $list[$count-1] == -1 ||
                 $list[$count+1] == 1) {
                 print ("$list[$count]\n");
                 $count += 1;
         }

     Really, how cumbersome can you get? The author needs a full page of
     analysis to explain that! A foreach, array interpolation or even $#list
     would have done it so much better! Yes, TIMTOWTDI, but why present that
     one?

   * p. 128, the Tip box `One of the problems with Perl is that it is
     sometimes difficult to distinguish the following scalar variable or
     array-element values:

        o The null string "", which is converted to 0 in numeric expressions

        o An undefined variable or element, which defaults to the null
          string, which in turn is converted to 0 in numeric expressions

        o The string 0, which is converted to the mumber 0 in numeric
          expressions

        o A non-numeric string such as string, which is converted to 0 in
          numeric expressions'

     One piece of advice to avoid this ``problem'' is

     `Initialize the scalar variable or array element to a value other than
     0 that you know is not going to appear naturally in your program, such
     as -99999.'

     This is too silly to put up as advice, especially when the author
     actually knows about defined, as proved by the entries on pp. 492 and
     493.

   * p. 135, Analysis of Listing 5.6 `If you like, you can write your loop
     in a different way and use $count as a subscript. For example:

         $count = 0;
         while ($count < @array) {
                 print("element $count+1: $array[ $count]\n");
         }

     BUG BUSTER: What's wrong with the above code? (And do you think it was
     tested by the author before putting it into the book?)

   * p. 147, Sorting a List or Array Variable The heading says ``List or
     Array Variable'', while the syntax diagram says

         retlist = sort (array);

     `In this syntax, array is the list to sort, and retlist is the sorted
     list.'

     So my question is: Is array an array, or is it a list? Everything seems
     to indicate that it's a list, so why call it array?

     And there's no mentioning of, or reference to, the possibilities of
     sort.

   * pp. 149 - 150 Reversing a List or Array Variable

         retlist = reverse (array);

     as for sort

     and so on for chop, join and split.

  ------------------------------------------------------------------------

Day 6 Reading from and Writing to Files

It's called a filehandle, not a File Variable, file-variable or any such
thing!

   * p. 164 Checking whether the Open Succeeded `If open returns 0, an error
     occured.'

     It's not 0, it's undef.

  ------------------------------------------------------------------------

Day 7 Pattern Matching

It's called a regular expression, ok? You might abbreviate it to regex.

   * pp. 202 - 204, the analysis of Listing 7.2 Uses half a page to fix a
     word counting program using split(/ +/, $line) to correctly handle
     whitespace in the beginning of $line and tabs, but doesn't bother to
     mention (or refer to a page which mentions) the magic split(' ', $line)
     which would have solved all the problems in one go.

     Yes, it has a purpose as an illustration. There is, however, no point
     in not helping people use the strengths of the language once your point
     has been made.

   * p. 207 Matching Any Letter or Number `[T]he range [a-z] matches any
     lowercase letter, and the range [A-Z] matches any uppercase letter.'

     Yeah, if you're naove.

   * p. 209, Table 7.1 `\B Match inside word'

     Nope, \B means ``Match if not on a word boundary'', that is, match if
     we're not between an \w and a \W. This could mean that we have \w both
     before and after (inside a word) or we could be anywhere where we're
     not next to a \w (definitely not inside a word.)

   * p. 211 Word-Boundary Pattern Anchors `The word-boundary pattern
     anchors, \b and \B specify whether a matched pattern must be on a word
     boundary or inside a word boundary. (A word boundary is the beginning
     or end of a word.)'' (my emphasis)

     If ``A word boundary is the beginning or end of a word'', how can you
     be ``inside a word boundary''?

     On the next page, we can read:

     `The \B pattern anchor is the opposite of \b. \B matches only if the
     pattern is contained in a word.'

   * p. 217, Table 7.2, Character-range escape sequences
          \w Any word character [_0-9a-zA-Z]

          \W Anything not a word character [^_0-9a-zA-Z]

     There's more to \w than [_0-9a-zA-Z].

     Good point: In this table, \s is [ \r\t\n\f], and \v is (correctly)
     gone.

   * pp. 228 - 229, Specifying a Different Pattern Delimiter `Perl enables
     you to use any pattern-delimiter character you like.'

     Well, unless you're aiming for the obfuscated Perl contest, you'll be
     glad that the above is wrong. Programming Perl says [5, pp. 41-42]:

     `Any non-alphanumeric, non-whitespace delimiter can be used in place of
     /. Also, if the opening delimiter is a parenthesis, bracket, brace or
     angle bracket, the closing delimiter will be the matching construct.'

     I know which book I believe.

     Good point: Mentions that if you use a regex metacharacter as your
     pattern delimiter, you can't use that metacharacter in your regex.

   * p. 232, Evaluating a Pattern Only Once Instead of showing you when and
     why /o is useful, our author provides us with the following masterpiece
     of program design and logic:

         $var = 1;
         $line = <STDIN>;
         while ($var < 10) {
                 $result = $line =~ /$var/o;
                 $line = <STDIN>;
                 $var++;
         }

     And then he explains that even though $var changes, the pattern used in
     the match is /1/. Very useful.

   * pp. 232-233, the Tip box `There's no real reason to use the o option
     for patterns unless you are keen on efficiency. Here's an easier way to
     do the same thing:

         $var = <STDIN>;
         $matchval = $var;
         $line = <STDIN>;
         while ($var < 10) {
                 $result = $line =~ /$matchval/;
                 $line = <STDIN>;
                 $var++;
         }

     The value of $matchval never changes, so the o option is not
     necessary.'

     An easier way to do the same thing as what? The previous example didn't
     do anything remotely like this! And why shouldn't efficiency be a
     reason to do something? If it isn't, why program in the first place?

   * p. 233 Using white space in patterns Doesn't explain (or doesn't know)
     that /x also allows ordinary comments in patterns. This could be
     because the book is for v. 5.001, so I'll ignore it for now.

   * p. 240 Specifying a Different Delimiter (for the s/// operator).
     Explicitly mentions that paired parentheses or angle brackets can be
     used as delimiters, but fails to mention braces or square brackets.
     Doesn't mention that you can still use these delimiters inside the
     pattern as long as they're balanced.

   * p. 242 Options for the Translation Operator The Note box immediately
     above says

     `The pattern special characters are not supported by the translation
     operator.'',

     but here he says:

     `For example, the statement

         $string =~ tr/\d/ /c;

     replaces everything that is not a digit with a space.'

     Since `the pattern special characters are not supported by the
     translation operator', the \d is simply d as far as tr/// is concerned,
     and the translation will replace everything that is not a d with a
     space.

   * pp. 243-244 Extended Pattern-Matching `Extended pattern-matching
     capabilities employ the following syntax:

         (?<c>pattern)

     <c> is a single character representing the extended pattern-matching
     capability being used, and pattern is the pattern or subpattern to be
     affected.'

     Well, in lookahead and non-capturing parentheses, there's a pattern in
     there, but otherwise, there's not. The way it stands, it would seem
     that (?i) would cause case-insensitive matching only for whatever
     pattern was inside the parentheses. Although the examples following
     this (mostly) use the special constructs correctly, this description is
     strange, if it's not definitely wrong.

   * p. 245, mid-page example `Embedded pattern options give you more
     flexibility when you are matching patterns. For example:

         $pattern1 = "[a-z0-9]+";
         $pattern2 = "(?i)[a-z]+";
         if ($string =~ /^($pattern1|$pattern2)$/) {
                 ...
         }

     Here, the i option is specified for some, but not all, of a pattern.'

     Absolutely not. Unfortunately, Programming Perl isn't as clear on this
     as it could have been. It simply says ``The case-insensitive [patterns]
     merely need to include (?i) at the front of the pattern'' [5, p. 69].

     There is no way to make only parts of a regex case-insensitive. A (?i)
     anywhere in your regex will make the entire match case-insensitive.
     Simply testing the pattern above agaist the string "A9" would've shown
     the author that his understanding of the regex is wrong.

     Mastering Regular Expressions is a bit more explicit:

     `You can accomplish [case-insensitive matching] by putting (?i)
     anywhere in the regex (usually at the beginning).'' [2, p. 231]

     and further on, discussing (?s) and (?m):

     `Although you may be tempted to want something like
     (?m)...(?s)...(?m)... to change the mode mid-stream, the line mode is
     an all-or-noting characteristic for the entire match.'' [2, p. 235].

   * p. 247, Q&A, 2nd Q
     `Q:
          why does pattern-memory variable numbering start with 1, whereas
          subscript numbering starts with 0?

     A:
          Subscript numbering starts with 0 to remain compatible with the C
          programming language. There is no such thing as pattern memory in
          C, so there is no need to be compatible with it.'

     Does this guy know what ``compatible'' means? And does he know that
     regex-wielding tools using backreferences existed before Perl?

     `Q:
          Why does Perl use characters such as +, *, and ? as pattern
          special characters?

     A:
          These special characters usually correspond to special characters
          used in other UNIX applications, such as vi and csh. [...]'

     Does this guy know the difference between regexes and globs? csh?
     Really!

  ------------------------------------------------------------------------

The Second Week

I'm not going in that kind of detail in the next two weeks, I'll just
highlight the grossest mistakes here.

  ------------------------------------------------------------------------

Day 8 More Control Structures

   * pp. 277, the Warning box, and 283, the Tip box. The Warning box on p.
     277 reminds you to update your counters when using next in a while or
     until loop. It ends with:

     `This, by the way, is why many programming language purists dislike
     statements like next and last - it's too easy to lose track of where
     you are and what needs to be updated.'

     This, by the way, is what the continue block is for. But when
     discussing this construct on p. 283, our author says:

     `Usually, it is better to use a for statement than to use continue with
     a while or an until statement, because the for statement is easier to
     follow.'

     No wonder he doesn't like next and last; he disallows the very
     construct that makes them useful! And mentioning how redo treats the
     continue block is deferred to the Q&A session at the end of the day.

   * p. 284, the goto statement Discusses only one of the three different
     gotos available in Perl, and for the one he discusses, he claims:

     `The statement to which label is assigned cannot be in the middle of a
     do statement or inside a subroutine.'

     I was able to compile and run the following program without warnings on
     Perl v.5:

         #!/store/bin/perl -w

         sub two {
             print "two, ";
             goto ONE;
             print "two again, ";
         }

         sub one {
             print "one, ";
             &two;

             ONE: print "one again, ";
             goto THREE;
             print "one once more, ";
         }

         &one;

         do { THREE: print "three\n" } if ($#ARGV<0)

     It prints out one, two, one again, three, as one could reasonably
     expect, and it violates both the restrictions above. Yes, there are
     restrictions on how you can use goto, but they are not the ones listed
     above.

     (I'm beginning to wonder whether any of the code in that book has been
     tested.)

  ------------------------------------------------------------------------

Day 9 Using Subroutines

For an author so fond of verbose programming, it seems strange that he
chooses to let the final statement of a subroutine be the return value (or
even assigning to a dummy $return value) instead of using return.

   * p. 302, the Note box ending on top of the page `In Perl, my and local
     behave identically and use the same syntax. The only difference between
     them is that variables created using my are not known outside the
     subroutine.'

     This is about as wrong as you can be. Quoting Joseph N. Hall in
     Effective Perl Programming:

     `my has nothing to do with subroutines, local has nothing to do with
     subroutines, and of course the difference between them has nothing to
     do with subroutines. It may look that way, but the truth - as you will
     see - is something else entirely.'' [1, item 31]

     For a more thorough explanation, see the excerpts from [1] available
     on-line, [5] or even [2] (Yes, even that book, not even specific to
     Perl, displays more knowledge about Perl than the work discussed here.)

  ------------------------------------------------------------------------

Day 10 Associative Arrays

They're called Hashes now.

To me, quotes around the indices to a hash is more difficult to read. The
braces surrounding the index will quote any bare identifier anyway.

Good point: He emphasises that the order of the elements of a hash is
(seemingly) random.

   * p. 333 Explains that you can use => instead of ,. Doesn't say what the
     difference is.

     (Hint: => will quote any bare identifier to the left of it.)

   * p. 334, Listing 10.3 The last line is

         print ("Number of bananas: $fruit{\"bananas\"}\n");

     Works? Yes. Readable? No. Pretty? No. Why can't he say (any of)

         print "Number of bananas: $fruit{bananas}\n";
         print "Number of bananas: $fruit{'bananas'}\n";
         print "Number of bananas: $fruit{q[bananas]}\n";
         print qq/Number of bananas: $fruit{"bananas"}\n/;

     or anything else to avoid the \" inside the braces?

   * pp. 338 - 355 Creating Data Structures Using Associative Arrays The
     entire section is obviously a clean copy from the previous version of
     the book. It still works, of course, but why make it hard for yourself?
     A complete re-write using references and multidimentional data
     structures is the only cure for this section.

  ------------------------------------------------------------------------

Day 11 Formatting Your Output

For an author who seems obsessed with the idea of avoiding any use
whatsoever of Perl's special variables, our author seems curiously willing
to (ab)use $~ and $^ today. Why can't he brush these two under the same
carpet where all the other special variables are and use MYFILE and
MYFILE_TOP as his format names? Ah, he doesn't want to have MYFILE mean two
different things! But introducing $~ is OK? Perhaps there just wasn't any
more space under the carpet.

Anyway, use FileHandle; or, for 5.004, use IO::Handle; would've solved any
of these headaches:

    use FileHandle;
    MYFILE->format_name("MYFORMAT");
    MYFILE->format_top_name("MYTOPFORMAT");

but when you don't know your library, that's what you get: headaches.

   * p. 382, Eliminating Blank Lines When Formatting `You can eliminate
     blank lines [...]. To do this, put a ~ character at the beginning of
     any output line that is to be printed only when needed.'

     Wrong. The ~ can be anywhere on the line. This is not just nitpicking,
     since the ~ will be replaced with a space on output. Thus, if you want
     to supress blank lines without starting the lines with a space, you'll
     put the ~ somewhere else, typically at the end of the line.

   * p. 383, Supplying an Indefinite Number of Lines `To [...] use as many
     lines as necessary, specify two ~ characters at the beginning of the
     output line containing the value field.'

     Wrong. The ~~ can be anywhere on the line. See the previous point.

  ------------------------------------------------------------------------

Day 12 Working with the File System

Good point: Uses open || die quite early in the chapter. Unfortunately, it
is not used during the description of the open function, so you won't see it
if you went for open from the index.

Good point: Actually covers the difference between eof, eof() and eof(FILE).

 ... and gets it right.

And it's called a directory handle, not a directory variable.

Working out what (gm|local|u)?time does in a chapter called Working with the
File System will take someone more clever than me.

   * pp. 407 - 408 `If you want to read data as quickly as possible, you can
     call sysread instead of read.'

     Sure, I want to read ``as quickly as possible''. Beam me up, Scotty! I
     hope all the people getting in trouble with sysread because of this guy
     goes to him for help, and not to comp.lang.perl.misc.

     Yes, there's a Warning box (on the next page) saying ``Don't use
     sysread and syswrite unless you know what you are doing.'' But if I
     know what I'm doing, I wouldn't need this book to tell me more than

     `sysread is equivalent to the UNIX function read.'

     What I would need the book to tell me (which it doesn't) is that this
     bypasses perl's internal buffering, and that mixing sysread with read
     or syswrite with write or print on the same filehandle is going to give
     me problems.

   * p. 427 Doesn't know (or care) that gmtime and localtime return
     different values depending on context.

   * p. 430, Q & A
     `Q:
          Which is better to use: the file-test operators or the built-in
          function stat?'

     (So stat is a built-in function and not a library function like all the
     others? What's so special about stat?)

     `A:
          Whenever possible, use the file-test operators. They are easier to
          use and are often more efficient.'

     They may be easier to use, but since they're built upon a stat anyway,
     there's really no way they can be faster. If the author wanted to help
     people speed such things up, why not tell them about the special _
     filehandle instead?

  ------------------------------------------------------------------------

Day 13 Process, String and Mathematical Functions

A seemingly random collection of various functions

Good points:

   * p. 436, Listing 13.2 Actually uses eval for something useful; checking
     whether a function is implemented.

   * p. 438, The fork Function Actually mentions that the error return value
     can be checked with defined. But of course, with fork, the difference
     between 0 and undef suddenly matters.

Bad points:

   * p. 442 The die and warn functions Doesn't mention $! which is ever so
     useful in warn and die.

   * p. 445 The wait and waitpid functions `The wait function [...] waits
     for a child process to terminate (such as a process created by fork).'

     As if there were other kinds of child processes.

  ------------------------------------------------------------------------

The Third Week

  ------------------------------------------------------------------------

Day 14 Scalar-Conversion and List-Manipulation Functions

   * p. 482 and 486 After spending an entire page on the table presenting
     the format characters to pack, it's only fair to spend the same amount
     on the equivalent table for the unpack function, four pages later!
     Well, if you're paid by the page it makes perfect sense.

     Says that n and N stores a short and a long in ``network order'',
     without bothering to explain what ``network order'' means.

   * p. 493, the Note box `The general rule is: A function that returns the
     null string when an error or exceptional condition occurs is usually
     really returning the undefined value.'

     Finally! The truth! Now leave it to the reader to figure out when
     ``usually'' applies and when it doesn't.

     I'm not sure whether this paragraph makes me feel better or worse about
     the author of this book. On one hand, he actually knows about defined
     and the undef value, and that this is in fact the return value of quite
     a few functions. On the other hand, it means that He has knowingly
     misled his readers throughout the entire book! To me, that's just
     completely unacceptable!

   * p. 495 Array and List Functions `The following functions manipulate
     standard array variables and the lists that they store:'

        o grep Nope, grep works on LISTs, not ARRAYs

        o splice Yes

        o shift Yes

        o unshift Yes

        o push Yes

        o pop Yes

        o split Huh? split doesn't work on a LIST at all!

        o sort Nope, sort works on LISTs, not ARRAYs

        o reverse Nope, reverse works on LISTs, not ARRAYs

        o map Nope, map works on LISTs, not ARRAYs

        o wantarray Huh? What's this supposed to mean?

     What's so difficult? You can use an ARRAY where you want a LIST, but
     not the other way around.

   * p. 496, The grep Function First states that grep has the syntax

         foundlist = grep (pattern, searchlist);

     But later, p. 497, admits that grep ``can be used to search for any
     expression, not just patterns.'' Demonstrates this, listing 14.10, by
     using grep(-r, readdir(CURRDIR)), which must be deeply confusing, since
     he hasn't told anyone that the -X file test operators operate on $_ by
     default, nor that grep EXPR, LIST locally sets $_ to each element of
     the LIST given and returns the elements of LIST for which EXPR
     evaluated to whatever perl considers true.

     As a consequence of this, he doesn't tell you that $_ refers to the
     actual elements of the list, and thus that the list can be modified.

     Nor does he touch upon the similarities between grep and map.

     Nor does he tell anyone of the grep BLOCK LIST syntax. Oh, well, that's
     a 5ism.

   * p. 506 The shift Function `If you do not specify an array [...], The
     Perl interpreter assumes [...] the system array variable @ARGV. [...]
     This default feature of shift makes it handy for processing
     command-line arguments.'

     So the author who's shunned default arguments and hidden variables for
     500 pages suddenly comes forth and declares a default argument
     ``handy''. Now there's an interesting change of opinion!

     Oh, and he doesn't mention that shift actually shifts @_ by default in
     a subroutine. Any aspiring programmer trying

         #!/usr/bin/perl

         &process_args;
         # rest of program

         sub process_args {
             while ($arg = shift) {
                 ...
             }
         }

     is in for a disappointment.

   * p. 506, The Note box `shift returns the undefined value (equivalent to
     the null string) if the list is empty'

     shift doesn't work with lists at all, only with arrays.

   * p. 513 Here we have a Warning box warning that pop returns undef if
     used on an empty stack, and that you should check your return value
     with defined. This is all well. Strangely enough, shift (which might
     just as well be used for a stack or queue) didn't need a similar
     warning. A simple Note (see above) was sufficient in this case.

     Oh, and if someone happens to push or unshift any undefs on the stack,
     there are going to be surprised programmers out there.

   * p. 513, The split Function The only place I've seen a more superficial
     treatment of split is elsewhere in this very book. If you want to
     understand how split works, see [2, pp. 259 - 265].

     He tells you

        o that ``It splits a character string into a list of elements''

        o that you can limit the number of fields with the optional third
          argument.

     He doesn't tell you

        o that split will strip trailing null fields.

        o that split with a large (or negative) limit will retain those
          trailing null fields.

        o that split works on $_ by default.

        o that split will split on whitespace, ignoring leading fields, if
          the PATTERN is also omitted.

        o that split will split on whitespace, ignoring leading fields, if
          the special value " " is given as the PATTERN.

        o what happens when the PATTERN contains parentheses. Doesn't even
          warn you about unexpected things happening.

   * p. 516, The map function This time we're actually told that $_ is set
     to each element of the LIST in turn. We're not told that we can modify
     the LIST through $_.

   * p. 517, The wantarray function `In Perl, the behavior of some built-in
     functions depends on whether they are dealing with scalar values or
     lists. For example, the chop function either chops the last character
     of a single string or chops the last character of every element of a
     list:

         chop($scalar);      # chop a single string
         chop(@array);       # chop every element of an array

     [...]'

     This is absolute nonsense! wantarray hasn't got anything to do with the
     arguments of a subroutine, but with the context in which the subroutine
     is called! Quoting perlfunc(1):

        o wantarray Returns TRUE if the context of the currently executing
          subroutine is looking for a list value. Returns FALSE if the
          context is looking for a scalar. Returns the undefined value if
          the context is looking for no value (void context).

              return unless defined wantarray;    # don't bother doing more
              my @a = complex_calculation();
              return wantarray ? @a : "@a";

  ------------------------------------------------------------------------

Day 15 System Functions

Well, after having spent days leisurely walking through different issues,
we're going to be busy today. On todays agenda is:

   * ([gs]et|end)(gr|pw)(nam|ent|u?id)

   * (get|set|end)(net|host)ent and get(net|host)by(addr|name)

   * getlogin, [gs]etpgrp and getp?pid

   * [gs]etpriority

   * (get|set|end)(proto|serv)ent, getprotoby(name|number) and
     getservby(name|port)

   * chroot

   * ioctl (!)

   * alarm

   * select (the four-argument one)

   * dump

   * socket, bind, listen, accept, connect, shutdown, socketpair,
     [gs]etsockopt and get(sock|peer)name

   * require, inserted as an afterthought during the discussion of System V
     IPC functions

   * msg(get|snd|rcv|ctl)

   * shm(get|write|read|ctl)

   * sem(get|op|ctl)

Not bad for a single day, is it?

Several places you're told to look for constants like AF_INET in the header
files. Seems our author doesn't know about h2ph or its output. Still lost in
Perl 4 land here.

Of course, this book is not about network programming, so you can't expect
to have everything about network programming in perl explained here either.
As a day's work in a 21 day self-study course ``with no previous programming
experience assumed'', it's absolutely meaningless. You'll need a respectible
amount of network programming under the hood to negotiate this day's lesson.
For reference, though, it's good to see the various functions in code
snippets.

If he wanted to enable people to actually use e.g. sockets, he could have
pointed people to the IO::Socket manpage. But then, the library obviously
isn't interesting or useful enough to mention.

   * p. 546, Listing 15.4

         gethostbyaddr ($packaddr, 2))) {

   * p. 556, Listing 15.10

         $oldpriority = getpriority (2, $userid);
         setpriority (2, $userid, $oldpriority + 1);

   * p. 563, The dump Function Claims dump is defined only in Perl 5.

     Why not spend your breath telling people to forget dump and undump and
     look towards the compiler instead?

   * p. 565 `To create an address suitable for passing to bind, call pack.

         $address = pack ("Sna4x8", 2, $portnum, $intaddress);

     ...'

   * p. 566, Listing 15.11

         $serveraddr = pack ("Sna4x8", 2, $port, $rawserver);
         socket (SSOCKET, 2, 1, $prototype) || die ("No socket");

   * p. 567, The Tip box `Note that enclosing a command in backquotes works
     for any UNIX command that returns output. For example, the statement

         $userid = 'whoami';

     assigns the current login user ID ...'

     Except that the cited example uses single quotes.

   * p. 568, Analysis of listing 15.11 `(Note that the values 2 and 1 passed
     to socket are, respectively, the local values of the constants PF_INET
     and SOCK_STREAM. [...] You likely will not need to use any other values
     for these arguments.)'

     So, hard-coding admitted ``local'' values and assuming nobody will ever
     have any use for Unix-domain and/or datagram sockets is universally
     valid?

   * p. 569, Listing 15.12

         $clientaddr = pack ("Sna4x8", 2, 0, $rawclient);
         $serveraddr = pack ("Sna4x8", 2, $port, $rawserver);
         socket (SOCKET, 2, 1, $prototype) || die ("No socket");

And so on for all the networking examples in this chapter. I won't quote
them all.

   * p. 574, The UNIX System V IPC Functions `Before you can use any System
     V IPC Functions, you first must [...] add the following statements to
     your program [...]:

         require "ipc.ph";
         require "msg.ph";
         require "sem.ph";
         require "shm.ph";

     [...]' (My emphasis)

     Really? Do I have to require "sem.ph"; to use the msg(get|snd|ctl)
     functions?

     Ok, I'm nitpicking again, but the above is both outdated and
     technically inaccurate.

  ------------------------------------------------------------------------

Day 16 Command-Line Options

Finally, Finally, we get to the -w flag. At last!

   * p. 585, 2nd Warning box `Options specified on the command line override
     options specified in the header comment. For example, if your header
     comment is

         #!/usr/local/bin/perl -w

     and you start your program with the command

         $ perl -s test1

     the program will run with the -s option specified but not the -w
     option.'

     This was true previously, but not since v.5 appeared. Strangely enough,
     the reason for this warning being wrong is exactly the same as for the
     other warning on the page being correct. What gives?

   * p. 595 Here is an example that typography and markup is not a trifle.
     The author is trying to explain that the -- flag indicates ``end of
     options'', but his markup changes two consecutive dashes to an
     <em-dash>. The result looks like this:

     `The special argument <em-dash> <em-dash> also indicates ``end of
     options.'' For example, the following command treats -w as an option
     and -e as an ordinary argument. The <em-dash> <em-dash> is thrown away.

         $ perl -s testfile -w <em-dash> -e

     [...]'

   * p. 595 - 603 We're treated to a nine-page introduction to cpp(1). In a
     book on Perl. Go figure. Especially since the use of -P has gone so
     completely out of fashion.

   * p. 605, the Note box

         while (< >) {

     (Note the space in < >). That just won't work.

   * p. 610, Listing 16.5

         #!/usr/local/bin/perl

         # This program is called with the -a and -n options.
         while ($F[0] =~ /[^\d.]/) {
                 shift (@F);
                 next if (!defined($F[0]));
         }
         print ("$F[0] $F[1]\n");

     Do you believe the comment on line three? 'Cos I don't.

   * p. 615, Listing 16.8. A Perl program contained in a file. `Listing 16.8
     is a simple example of a program that works if run with the -x option.'

     Type

              Here is a Perl program which appears in the middle
              of a file.
              The stuff up here is junk, and the Perl interpreter
              will ignore it.
              The next line is the start of the actual program.
              #!/usr/local/bin/perl

              print ("Hello, world!\n");
              __END__
              This line is also ignored, because it is not part
              of the program.

     Output

              $ program16_8
              Hello, world!
              $

     The Output section indicates that if you make the file program16_8
     containing the above listing executable, running it will produce the
     output reproduced on the second line. The Analysis section immediately
     contradicts this:

     Analysis
          If this program is started with the -x option, the Perl
          interpreter skips over everything until it sees line 6. (Needless
          to say, if you try to run this program without specifying the -x
          option, the Perl interpreter will complain.)

     `the Perl interpreter will complain'', will it? But it didn't,
     according to the example run just a couple of lines previously!

   * p. 616, The -U option `The -U option tells the Perl interpreter to
     enable you to perform ``unsafe'' operations in your program.
     (Basically, you'll know that an operation is cosidered unsafe when the
     Perl interpreter doesn't let you perform it without specifying the -U
     option!)'

     So, whenever ``the Perl interpreter'' won't let me do something, I'll
     try with -U and see if it lets me? C'mon!

I'll resist my urge to quote the descriptions of -D and -T. I'll also resist
quoting the Q&A describing how to write ``machine-independent'' scripts
using -P and #include <perldef.h> together with #ifdef/#endif sections.

  ------------------------------------------------------------------------

Day 17 System Variables

I can't believe that somebody has actually written an 870 pages book on Perl
without giving a thorough description of $_ before page 622. (``Thorough''
in the loosest possible sense of the word.)

   * p. 622, The default Scalar Variable: $_ `The following functions and
     operators work with the $_ variable by default:

        o The pattern-matching operator

        o The substitution operator

        o The translation operator

        o The <> operator, if it appears in a while or for conditional
          expression

        o The chop function

        o The print function

        o The study function

     Humm. I think I'll add a bit to that list:

        o -X tests, lstat, stat

        o abs, sin, cos, log, exp, sqrt

        o alarm

        o chomp, length, pos

        o chr, ord, hex, oct, int

        o chroot

        o defined, require, ref

        o eval

        o glob

        o gmtime

        o lc, lcfirst, uc, ucfirst, quotemeta

        o readlink, unlink, rmdir

        o split

     Oh, and don't forget that map and grep will set $_ locally. Seems $_ is
     even more ubiquitous than our author realised.

   * p. 624, Listing 17.1. A program that counts using tr

         while ($input = <>) {
                 $_ = $input;
                 ...
         }

     Isn't worth wasting a comment on.

   * p. 640, Multidimensional Associative Arrays and the $; Variable `Perl
     does not support multidimensional associative arrays directly. The
     following statement is not a legal Perl statement:

         $myvar = $array{"foo"}{"bar"};

     However, Perl enables you to simulate (sic) a multidimensional
     associative array using the built-in system variable $;'

     Seems we're a bit out of touch with the last few years of Perl
     development.

   * p. 650, The $+ Variable `The $+ variable matches the last subpattern
     enclosed in parentheses. For example, when the following pattern is
     matched, $+ matches the digits after the decimal point:

         /(\d+)\.(\d+)/

     This variable is useful when the last part of a pattern is the only
     part you really need to look at.'

     This is wrong, it completely misses the point, and it makes $+ look
     like just another useless Perl feature. Perhaps it's not the most often
     used feature of Perl, but boy is it handy when you need it!

   * p. 654, Buffering Output: $|, the Warning box `If you want to eliminate
     buffering for a particular file, you must set $| before writing to the
     file for the first time because the operating system creates the buffer
     when it performs the first write operation.'

     Not on my system, it doesn't. Setting $| immediately flushed the
     buffers and kept them flushed. I don't know if this is guaranteed
     behaviour, though.

   * p. 658, The %SIG Variable Doesn't know about references to subroutines
     or anonymous subroutines, both of which are useful for signal handlers.

Today, we see the first occurence of use, describing how to use English; to
avoid all those nasty $#@%& variables.

Oh, and the deprecations of $# and $* are Warnings, while the deprecation of
$[ is simply a Note. Does that make any sense?

  ------------------------------------------------------------------------

Day 18 References in Perl 5

To do this day full justice, it should be quoted in its entirety.
Unfortunately, I don't have the patience to do this. Besides, this review is
far too long already. Tom Christiansen also has some comments on this and
the next chapter.

The CD-ROM included with this book doesn't include any listings from this or
the next day. Any quoted code here is therefore typed in, as scrupulously as
possible, by myself. Seeing the quality of the code, I begin to understand
why they didn't want it to be easily accessible.

This chapter is so unbelievably bad, the only good thing I can find to say
about it is that the string ``use strict'' appears in it.

Most of the time, I'm only quoting paragraphs and excerpts. When the error
is not obvious, I'll comment on it also.

   * p. 667-668, Introduction to References `A reference is simply an
     address to a value. [...] In Perl, you can refer to a pointer as a
     reference; in fact, you can use the terms pointer and reference
     interchangeabply without any loss of meaning.'

     `Perl is object-oriented in itself because everything in Perl is an
     object.'

     `To use hard references as anything but scalars, you have to explicitly
     de-reference the variable and tell it how you want it to behave. If
     this sounds confusing, don't worry; references are covered on Day 19,
     ``Object-Oriented programming in Perl,'' to help make this concept
     clearer.'

     That last point is very reassuring. Especially in a chapter called
     ``References in Perl 5''.

   * p. 670, The Note box `A Pointer is an address. The data at that address
     is referred to by a pointer. If the pointer happens to point to an
     invalid address, you can get bad data. Generally, Perl will simply
     return a NULL value, but you should not rely on this, and should
     program to initialize all your pointers to refer to valid data items.'

   * p. 670, References and Arrays `[...] the most important [thing to]
     remember about Perl is that all Perl @ARRAYs and %HASHes are always
     one-dimensional.'

     This becomes especially amusing considering the heading on p. 675:
     Multidimensional Arrays.

   * p. 671 Referring to the Perl script/program as a ``shell script''.

     Calling the script `test'. (And apparently running it without
     troubles!)

     Talking about ``the address of ARGV''.

     `a reference to a one-dimensional array is simply a pointer to the
     first element of the array.'

   * p. 671, The Note box `Pointers are referred to as references, and vice
     versa.'

   * p. 673 `you don't have to [use] the comma operator. You can use the =>
     operator instead. [...] The => operator [is] the same as the comma
     operator.'

   * p. 675 `You create a reference to an array through the statement @array
     = list.'

     `Perl gives you a lot of opportunity to mystify yourself and improve
     your social life.'

   * p. 677, Listing 18.6 Creating a hash with only integers as indices.

   * p. 679 `See a book on object-oriented programming to get more
     information on closure.'

   * p. 679 `The code within a sub is simply a declaration created through a
     previous statement. The code within the sub is not executed
     immediately, however. It is compiled and set for each use.'

     `This output reflects that the assignment of $x, $y, and $z was done
     when the first declaration of print_coor was encountered as a call.'

     Does this guy know what declaration, statement, assignment and compile
     mean? It is not often I come across writing so contorted that it
     confuses me about something I understood perfectly well before reading
     about it.

   * p. 680, Listing 18.8 Using Closures.
     Type

              #!/usr/bin/perl

              sub errorMsg {
                       my $lvl = shift;
                      #
                      # define the subroutine to run when called.
                      #
                       return sub {

                      my $msg = shift;  # Define the error type now.
                      print "Err Level $lvl:$msg\n"; }; # print later.
                       }

              $severe  = errorMsg("Severe");
              $fatal = errorMsg("Fatal");
              $annoy = errorMsg("Annoying");

              &$severe("Divide by zero");
              &$fatal("Did you forget to use a semi-colon?");
              &$annoy("Uninitialized variable in use");

     Output

              $severe  = errorMsg("Severe");
              $fatal = errorMsg("Fatal");
              $annoy = errorMsg("Annoying");

     Strange, that's not the output I get.

     Seriously, the code, strange indentation and all, works as intended,
     but the claimed output is simply ridiculous. Boy are people going to be
     confused until they've given up and typed the example in and run it.

     `Sounds confusing? It is. This is primarily the reason you do not see
     such code in most Perl programs.'

     I guess the author should try sorting out some of his own confusion
     before trying to confuse others with it.

   * p. 681 `In the subroutine in Listing 18.9, the assignment my (@a, @b) =
     @_ gets loosely interpreted by your Perl interpreter as, ``Let's see,
     @a is an array, so assign one array from @_ to @a and then assign
     everything else to @b.'' Never mind that the @_ is itself an array and
     will therefore get assigned to @a, leaving nothing to assign to @b.'

     What a load of rubbish! Having typed that makes my hands feel dirty.

   * p. 682 `[to have more than one array argument], you have to pass arrays
     in by reference, which you do [like this]:

         #!/usr/bin/perl

         [...]

         $i = 0;
         sub listem {
             my ($a, $b) = @_;
             foreach (@$a) {
                print "a[$i] = " . @$a[$i] . " " . "\tb[$i] = " . @$b[$i] ."\n";
                 $i++;
                 }
             }

         [...]

     Interesting combination of four- three- and one-position tabs there.
     Especially noteworthy is the use of a global variable as a loop index!
     We can also point out the use of single-element slices (probably not
     intended) and the concatenation of the strings to print. (Especially "
     " . "\tb[$i] = " is neat!

   * p. 683, last line: `Hold that thought: Don't use globals.'

     Look who's talking!

   * p. 684, References to File Handles

         spitOut(\*STDIN);

     Yess!

     (for the curious, spitOut prints to the filehandle.)

   * p. 684 `In UNIX (and other operating systems), the asterisk is a sort
     of wildcard operator. In Perl, you can refer to other variables and so
     on by using the asterisk operator.'

     Talks of %_main and ``package context''.

     `When evaluated, a typeglob produces a scalar value that represents the
     first objects of that name. This includes file handles, format
     specifiers, and subroutines.'

   * p. 685 (In a section called ``Using Symbolic References... Again''!)

     When you work with hashes, you have to create an extra reference to the
     index. In other words, you cannot use something like this:

         $clients { \$credit } = "despicable" ;

     The \$credit variable will be converted to a string and won't be used
     correctly as an index in the hash. You have to use a two-step procedure
     such as this:

         $chist = \@credit;
         $x{ $chist } = "despicable";

     [...]'

     I know what's despicable here, and it's got nothing to do with credit.

   * p. 686 `When preceded by the @ operator, curly braces enable you to set
     up small blocks of evaluated code. [...]

         print "The midpt is @{[&average($x,$y,$z)]} \n";

     [...] the contents of the @{} are evaluated as a block of code. The
     block creates a reference to an anonymous array that contains the
     results of the call to the subroutine average($x,$y,$z). The array is
     constructed because of the brackets around the call.'

   * p. 688, Summary `The two types of references in Perl 5 are hard and
     symbolic. Hard links work like hard links in the UNIX file systems.
     [...] Symbolic links [...] are useful in providing multiple stages of
     reference to objects.'

     (Why does he suddenly start talking about links?)

     `References are used to create and refer to objects, constructors, and
     packages.'

  ------------------------------------------------------------------------

Day 19 Object-Oriented programming in Perl

   * p. 692 `What might be a new concept to Perl 4 programmers is the use of
     the double colon (::) to signify the base and inherited classes.'

     The :: has nothing to do with inheritance.

   * same page Calls the single quote ``the back quote (') operator''.

   * p. 693, the Note box `Time now for a shameless plug for Perl Unleashed
     [...] due the summer of 1996.'

     Tom Christiansen has already written a review of that one.

   * same page over to next Seems to believe that calling the constructor
     new is a requirement, when it is in fact simply a convention.

   * p. 695

         push (@INC, 'pwd');
         use Cocoa;

     See the review of Perl 5 unleashed for why this is stupid. Only with
     single quotes instead of backticks it's even more stupid. (Do you
     usually keep your libraries in subdirectories called pwd?)

   * p. 700 Uses barewords in @EXPORT. Doesn't mention @EXPORT_OK.

   * p. 701 Uses commas in qw.

     Uses print statements like

         print "import " . $_ . ";\n";

   * p. 703

         $method = $local ? "Quava::" : "Espresso::";
         $cup->{$method}grind(@args);

   * p. 708 Uses commas in qw.

   * p. 710 `Packages and modules in Perl provide a great deal of data
     encapsulation with the use of the my construct.'

  ------------------------------------------------------------------------

Day 20 Miscellaneous Features of Perl

   * p. 718, the Tip box `You should use unshift, not push, to add to the
     @INC array.'

     Seems our authors don't even read each others' chapters. Mr. Husain
     didn't know this just 23 pages ago. Oh, and apparently none of them
     knew that use is a compile-time statement, while any modifications of
     @INC using push or unshift are visible at run-time only.

   * p. 723 `A useful trick is to use newline characters as delimiters:

         q
         this is my string

     This example is equivalent to the following because the newline after
     the q indicates the beginning of the string, and the newline after
     string indicates the end of the string:'

     Oh yes, very useful. Except that it's no longer legal syntax.

   * p. 723, the Note box discussing q and qq `Be careful not to leave a
     space between the q or qq and the left parenthesis; if you do, the Perl
     interpreter will assume that the space character, not the (, is the
     delimiter.'

     Duh! And why limit yourself to parentheses? Any of < { and [ will do as
     well.

   * p. 724, Defining Strings Using ltlt Of the six examples on this page
     and the next, none of them will actually work. They are all missing the
     ; on the end.

     `Single-quoted end-of-string characters behave like normal
     end-of-string characters.'

     (By ``normal'', he means unquoted)

     No, they don't. unquoted defaults to double-quoted, and will perform
     variable interpolation.

     `Double-quoted end-of-string characters are searched for variable
     names, which are replaced by their values if found.

         $endchars = "END";
         $longstring = <<"$endchars"
         Here is the first part of the string.
         Here is the last part of the string.
         END
         # here is the next statement

     Is it too much to ask that the author knows his FAQ and tests his code
     before rushing off to the publisher with it?

   * p. 731, the Do/Don't box
     Don't
          use aliases unless you absolutely must, because they can become
          very confusing.

     Do,
          instead, substitute the variable name into a string and then
          execute it using eval. This is a better way to reference a
          variable indirectly.

     Hello!? eval with interpolated variable names is less confusing than
     typeglobs? Haven't you heard about references?

   * p. 732, Packages Here comes packages! forty pages after the chapter on
     Object-Oriented programming! Whee!

   * p. 733, Referring to One Pachage from Another Leads you to believe that
     ' is the preferred package/variable delimiter.

         print ("$mypack'var\n");

     The :: is only mentioned in a Note box.

   * p. 737, Modules Not bad. At least, a lot better than the corresponding
     section in the previous chapter. Here, @EXPORT and @EXPORT_OK are both
     presented and qw is used correctly.

     Whoops, he seems to think that variables and subroutines inside the
     package is protected from the outside world. Somebody should have told
     him about fully qualified names.

   * p. 739, Using Predefined Modules At last! I was wrong all the time! He
     does know about the library. He just didn't want to tell you about it
     until you had matured enough to comprehend it!

     `The following are some of the most useful modules in this library:
     [integer, diagnostics, English, Env, POSIX, Socket].'

     ... but you didn't do much to justify that statement, did you? And how
     do you know what's most useful to me, if I may ask?

   * p. 740, the Tip box A reference to CPAN! I don't believe it!

   * p. 740, Using Perl in C Programs `Perl 5 enables you to call Perl
     subroutines from within C programs. To add this capability, you need to
     do two things: add references to Perl to your program source, and then
     link the Perl library when you compile your program.

     See the Perl documentation for more details on how to use Perl
     subroutines in C programs.'

     That's all there is to it!

   * p. 740, Perl and CGI Scripts `The Common Gateway Interface (CGI) is a
     standard for interfacing external applications with information servers
     (such as those found on the World Wide Web).

     For more information on CGI, go to the Web page located at
     http://hoohoo.ncsa.uiuc.edu/cgi. A library of CGI scripts written in
     Perl can be found at http://www.bio.cam.ac.uk/web/cgi-lib.pl.txt.'

     The book boasts ``EXPLORE techniques for CGI and server-side
     scripting'' on the front cover, and this five-line paragraph is
     everything you're going to hear about CGI in the entire 870 page book!
     Aren't there any laws agains misleading advertisements in the U.S.?

  ------------------------------------------------------------------------

Day 21 The Perl Debugger

Why bother? If you didn't need the debugger for getting through all the
misfeatured and erroneous code presented during the first 20 days, you're
never going to need it. That's all I'm going to say about this chapter.

  ------------------------------------------------------------------------

Conclusions

This book is so bloated, it's incredible. Just a s/the Perl
interpreter/Perl/g would cut 30 pages total. Cut all non-working code
examples and keeping the working ones would cut another 120 pages. Removing
duplication of information and information-free text would cut at least 45%,
and a less noisy layout would cut another 30%.

What remains may or may not be good enough to publish, given a proper
reworking of the language and order of presentation, and it could probably
make quite a nice leaflet.

If you didn't get the picture yet:

This book is a waste of your time and money. They're both better spent
elsewhere. Get a real book.

Thank you for your attention.

Tromsx, 23. July 1997

  ------------------------------------------------------------------------

References

[1]  Effective Perl Programming, by Joseph N. Hall, Addison-Wesley
     Developers Press, not yet in press, See
     http://www.5sigma.com/perl/book.html or
     http://www.aw.com/devpress/titles/41975.html for details and excerpts
     such as the cited paragraph, ISBN 0-201-41975-0.

[2]  Mastering Regular Expressions, by Jeffrey E. F. Friedl, O'Reilly &
     Associates, Inc., 1997, See http://enterprise.ic.gc.ca/~jfriedl/regex/
     or http://www.ora.com/catalog/regex/ for details and excerpts, ISBN
     1-56592-257-3.

[3]  Learning Perl 1/e, by Randal L. Schwartz, O'Reilly & Associates, Inc.,
     1993, This book has recently come out in a new edition, see
     http://www.ora.com/catalog/lperl2/noframes.html for details, ISBN (2/e)
     1-56592-284-0.

[4]  Programming Perl 1/e, by Larry Wall and Randal L. Schwartz, O'Reilly &
     Associates, Inc., 1991(?), ISBN ??

[5]  Programming Perl 2/e, by Larry Wall, Tom Christiansen & Randal L.
     Schwartz, O'Reilly & Associates, Inc., 1996, See
     http://www.ora.com/catalog/pperl2/noframes.html for details and
     excerpts, ISBN 1-56592-149-6.

[6]  teach yourself PERL 5 in 21 days 2/e, by David Till, Sams Publishing,
     1996, See
     http://www.mcp.com/2701839829008/cgi-bin/bag?isbn=0-672-30894-0&last=/bookstore
     or http://www.interlog.com/~davet/perl.html for details, errata etc.


-- 
	Tom Christiansen	tchrist@jhereg.perl.com

MAGIC*  xmg_magic;  /* linked list of magicalness */
    --Larry Wall, from sv.h in the v5.0 perl distribution


------------------------------

Date: 29 Jan 1998 05:52:35 GMT
From: sbushman@students.uiuc.edu (stewart samuel bushman)
Subject: URL problems in HTTP::Request call
Message-Id: <6ap5f3$qla$1@vixen.cso.uiuc.edu>


I'm trying to just get a script to call up a web page and download the
text (easy, huh?)  Well, I'm having problems with the initial URL call,
everything else works fine.  The text of the call is:

 my $req = new HTTP::Request POST=>'http://quote.yahoo.com/q?s=orcl';

Entering that URL into Netscape brings up the desired page, but apparantly
either the question mark or the equal sign is prohibiting perl from
entering the URL correctly.  Any ideas?

-stu

--
                   |
Stewart S. Bushman | The more I study religions the more convinced I become 
sbushman@uiuc.edu  | that man never worshipped anything but himself.
                   |     		- Sir Richard Francis Burton


------------------------------

Date: 8 Mar 97 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 8 Mar 97)
Message-Id: <null>


Administrivia:

The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc.  For subscription or unsubscription requests, send
the single line:

	subscribe perl-users
or:
	unsubscribe perl-users

to almanac@ruby.oce.orst.edu.  

To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.

The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.

The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.

For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V8 Issue 1758
**************************************

home help back first fref pref prev next nref lref last post