MeowChow has asked for the wisdom of the Perl Monks concerning the following question:
Well, it's been a few months, and I fear my Perl skills are getting rusty, but I'm almost certain the following lines should not be generating syntax errors:
| | @l = 1..10;
map { 1, 2 } @l;
map { "$_", 2 } @l;
|
eh?
MeowChow
s aamecha.s a..a\u$&owag.print
Re: map syntax bug-a-boo?
by chipmunk (Parson) on Nov 30, 2001 at 09:53 UTC
|
Curly braces can denote a block or an anonymous hash, and map can take a block or an expression, so map followed by a curly brace is ambiguous. Unfortunately, perl doesn't look forward to the closing brace to see whether it's a block or an anonymous hash, so perl has to guess.
If the opening curly brace is followed by a string and a comma (, or =>), perl guesses it's an anonymous hash. Anything else, and perl guesses it's a block. This heuristic works most of the time, but in some cases perl guesses wrong:
# a block returning a list of two elements,
# but perl thinks it's an anonymous hash
%hash = map { "$_", 2 } @l;
# an anonymous hash, but perl thinks it's a block
@hash_refs = map { $_, 2 }, @l;
However, there's not much urgency to fix this problem, because it's so easy to avoid:
# force parsing as a block
%hash = map { +"$_", 2 } @l;
%hash = map { ; "$_", 2 } @l;
%hash = map { ( "$_", 2) } @l;
# force parsing as an anonymous hash
@hash_refs = map +{ $_, 2 }, @l;
| [reply] [d/l] [select] |
|
Can I ask a silly question? What does the + mean to Perl in these examples. I don't ever recall seeing it ever used in such a way.
-Lee
"To be civilized is to deny one's nature."
| [reply] |
|
It's like making explicit the implicit '+' that precedes any non-negative number (think scalar ::= number or string).
Do you remember, when learning how to format numbers for output (using '%f', '%g', etc.) with printf in C, you had to account for the sign position? It would display as either a hyphen or blank. A blank, however, was analagous to a plus-sign.
Likewise, on input, non-negative numbers could optionally be expressed with a leading plus-sign. Since scalars (or scalar expressions) may be either numbers or a strings in perl, perl allows this with arbitrary scalar expressions.
dmm
You can give a man a fish and feed him for a day ...
Or, you can teach him to fish and feed him for a lifetime
| [reply] |
|
print (3-1)*2; # oops! print (...) interpreted as function ...
print +(3-1)*2;
sub foo { $foo }
$h{foo}; # equivalent to $h{'foo'}
$h{+foo}; # but maybe you meant $h{foo()}
See perlop for more on this curious operator. | [reply] [d/l] |
Re: map syntax bug-a-boo?
by dvergin (Monsignor) on Nov 30, 2001 at 08:41 UTC
|
Now, brethren and sistern, let's all charitabley
agree to stipulate that the
horrid "map in a void context"
was merely for the purpose
of reducing the problem to its bare essentials.
It would appear that, because of what you have
put inside the {...}, Perl is taking that to be an
expression and thus needing a comma after it.
use strict;
my @l = 1..10;
map { 1, 2 }, @l;
map { "$_", 2 }, @l;
does not produce errors. And if you say:
print map { 1, 2 }, @l;
print map { "$_", 2 }, @l;
you will see a bunch of hash-refs. So Perl is seeing
{1,2} as an anonymous hash
rather than as a BLOCK that happens to return
something. (A very reasonable reading
now that we look at it that way.)
------------------------------------------------------------
"Perl is a mess
and that's good because the
problem space is also a mess." - Larry Wall
| [reply] [d/l] [select] |
|
I was thinking along the same lines, but the fact that the following does work seems to contradict this argument, or at least imply that it's not the whole story:
map { $_, 2 } @l;
Though, now that I think about it, all this probably reflects a perl heuristic/optimization in the parser which says something along the lines of "if, within the bracketed expression, I see a constant and then a comma, I'm going to assume the expression is a hash, and not a block, no matter what comes afterwards...."
MeowChow
s aamecha.s a..a\u$&owag.print | [reply] [d/l] |
Re (tilly) 1: map syntax bug-a-boo?
by tilly (Archbishop) on Nov 30, 2001 at 08:51 UTC
|
The easy way to get it to parse the way you want is:
map {($_, 2)} @l;
| [reply] [d/l] |
(crazyinsomniac) Re: map syntax bug-a-boo?
by crazyinsomniac (Prior) on Nov 30, 2001 at 08:52 UTC
|
Try print {}; then
print {1 => 2};
and then
print {1 , 2}; and finally
print map { ( 1,2 ) } @l;
update: Howdy folks, I'm a slowhand luke
___crazyinsomniac_______________________________________
Disclaimer: Don't blame. It came from inside the void
perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;" | [reply] [d/l] [select] |
|
|