[Edinburgh-pm] Ingorance

Aaron Crane perl at aaroncrane.co.uk
Wed Mar 7 07:40:02 PST 2007


Andrew Smith writes:
> I was playing around with the attached test program  and don't 
> understand why line 8 doesn't prints *"1* rather  *"1 2 3"* for the 
> value $words[1], and just *2* for $words1[2] rather than *def*.
> as it does when printing the full array.  I think I understand that *qw* 
> puts single *'* around space delimited words which is why the double *"* 
> get included in  element 1.

Perl's C<qw> is actually implemented with C<split> on the inside.  You
can imagine that the compiler replaces every suitable occurrence of the
two letters "q" and "w" with this piece of text:

  split ' ', q

That is:

  qw/abc def ghi/
  # will turn into:
  split ' ', q/abc def ghi/

Since C< q/abc def ghi/ > is the same as C< 'abc def ghi' >, that means
that the result of the split is the same as C< ('abc', 'def', 'ghi') >.

The splitting happens at compile time, so there's no run-time penalty
for using C<qw> rather than any other literal list.  But there really is
an actual call to C<split> happening inside Perl when you use a C<qw>.
Imagining that C<qw> inserts C<'> where needed isn't going to be
productive.

Similarly:

  qw/abc "1 2 3" def/
  # will turn into:
  split ' ', q/abc "1 2 3" def/;

So the thing being split is C< q/abc "1 2 3" def/ >; when that gets
split on whitespace, the result is the same as this list:

  ('abc', '"1', '2', '3"', 'def')

That should explain why you get the behaviour you do with this bit of
your code:

  my @words1=qw/abc "1 2 3" def/;
  print join(":", at words1), "\n";
  print $words1[1],"\n",$words1[2],"\n";

That is, because the C< qw/.../ > has 4 chunks of whitespace, @words1
has 5 elements.  The first C<print> prints all five out, with colons
between; the second prints out the second and third elements on lines of
their own.  (Not the first and second, because array indexing is
0-based.)

As for the other chunk of code:

  my @words2=("abc","1 2 3","def");
  print join(":", at words2), "\n";
  print $words2[1],"\n",$words2[2],"\n";

The @words2 array is initialized with the three elements of the list you
give it, each of which is a string:

  "abc"         # $words2[0]
  "1 2 3"       # $words2[1]
  "def"         # $words2[2]

The quotes there are part of the syntax for literal strings, not part of
the data in the strings themselves.

So printing out all the elements of @words2, joined with a colon, produces

  abc:1 2 3:def

because you're not doing anything that could split $words2[1] on
whitespace.

-- 
Aaron Crane


More information about the Edinburgh-pm mailing list