I'm trying to declare magic numbers as constants in my Perl scripts, as described in perlsub. However, I get warnings:
$ cat foo.perl
use warnings ; use strict ;
sub CONSTANT() { 5 }
print 7-CONSTANT,"\n" ;
$ perl foo.perl
Ambiguous use of -CONSTANT resolved as -&CONSTANT() at foo.perl line 3.
2
$
The warning goes away if I insert a space between the minus and the CONSTANT
. It makes the expressions more airy than I'd like, but it works.
I'm curious, though: What is the ambiguity it's warning me about? I don't know any other way it could be parsed.
(Perl 5.10.1 from Debian "squeeze").
First, some background. Let's look at the following for a second:
$_ = -foo;
-foo
is a string literal[1].
$ perl -Mstrict -wE'say -foo;'
-foo
Except if a sub named foo
has been declared.
$ perl -Mstrict -wE'sub foo { 123 } say -foo;'
Ambiguous use of -foo resolved as -&foo() at -e line 1.
-123
Now back to your question. The warning is wrong. A TERM (7
) cannot be followed by another TERM, so -
can't be the start of a string literal or a unary minus operator. It must be the subtraction operator, so there is no ambiguity.
This warning is still issued in 5.20.0[2]. I have filed a bug report.
Look ma! No quotes!
system(grep => ( -R, $pat, $qfn ));
Well, 5.20.0 isn't out yet, but we're in a code freeze running up to its release. This won't be fixed in 5.20.0.
mpapec's answer helpfully referenced perldiag (which I wasn't aware of) but quoted the wrong diagnostic. The one I'm actually getting is
Ambiguous use of -%s resolved as -&%s()
(S ambiguous) You wrote something like -foo, which might be the string "-foo", or a call to the function foo, negated. If you meant the string, just write "-foo". If you meant the function call, write -foo().
So apparently the point is that -CONSTANT
is a valid bareword. I didn't know they could start with dashes.
I still don't really understand why that would give a warning here, given that (a) I'm using strict subs
so obviously I'm not going to throw around barewords deliberately, and (b) even if I were, a bareword or string in this position would be a syntax error anyway.
Edit: As pointed out (more or less) by tobyink, it is not actually that -CONSTANT
in itself is a bareword, but that strict subs
still allows barewords after the unary minus operator. Apparently the lexer isn't context-aware enough to know that parsing -CONSTANT
as an unary minus is not allowed in this context.
Still feels strange to me -- one would expect the effect of prototyping a sub with no arguments ought to be that I deliberately forfeit using that name as a bareword, no matter whether it happens to be as the operand to unary minus or in a different context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With