Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous use of -CONSTANT resolved as -&CONSTANT()

Tags:

perl

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").

like image 295
hmakholm left over Monica Avatar asked Apr 22 '14 09:04

hmakholm left over Monica


Video Answer


2 Answers

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.


  1. Look ma! No quotes!

    system(grep => ( -R, $pat, $qfn ));
    
  2. 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.

like image 55
ikegami Avatar answered Sep 27 '22 15:09

ikegami


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.

like image 24
hmakholm left over Monica Avatar answered Sep 27 '22 15:09

hmakholm left over Monica