views:

335

answers:

2

Does anyone know what parsing or precedence decisions resulted in the warning 'Use of "shift" without parentheses is ambiguous' being issued for code like:

shift . 'some string';

# and not

(shift) . 'some string'; # or
shift() . 'some string';

Is this intentional to make certain syntactic constructs easier? Or is it merely an artifact of the way perl's parser works?

Note: this is a discussion about language design, not a place to suggest

"@{[shift]}some string"
+7  A: 

Ambiguous doesn't mean truly ambiguous, just ambiguous as far as the parser had determined. shift . in particular is "ambiguous" because . can start a term (e.g. .123) or an operator, so it doesn't know enough to decide whether what follows is shift's operand or an operator for which shift() is the operand (and the parser isn't smart enough to know that: a) the . isn't the start of such a term or b) .123 isn't a valid operand for shift).

ysth
+20  A: 

With use diagnostics, you get the helpful message:

    Warning: Use of "shift" without parentheses is ambiguous at (eval
        9)[/usr/lib/perl5/5.8/perl5db.pl:628] line 2 (#1)
    (S ambiguous) You wrote a unary operator followed by something that
    looks like a binary operator that could also have been interpreted as a
    term or unary operator.  For instance, if you know that the rand
    function has a default argument of 1.0, and you write

        rand + 5;

    you may THINK you wrote the same thing as

        rand() + 5;

    but in actual fact, you got

        rand(+5);

    So put in parentheses to say what you really mean.

The fear is you could write something like shift .5 and it will be parsed like shift(0.5).

mobrule
I would upvote, but "my daily vote limit is reached." I think that's a bug, because I think SO went down for a few minutes right on the time when it was supposed to reset, so I'm being penalized for having voted yesterday.
Chris Lutz
in the case of rand (;$) i can see a case for the warning, however, with shift there doesn't seem to be, since shift's prototype (;\@) would prevent a string or number from being a valid argument
Eric Strom
@Eric Strom: this error comes from the tokenizer, which isn't that smart. Unrelatedly, shift's prototype isn't really (;\@), since that would make it a list operator and it is in fact a unary operator.
ysth
you mean prototype is lying to me... the horror
Eric Strom
no wait, why would (;\@) make it a list operator, i would interpret that prototype as taking zero arguments, or one which must be an @ array
Eric Strom
@Eric Strom: it just does; anything other than ($) or (_) is a list operator. Try with different prototypes: perl -we'sub foo (;\@) {} print foo @a, 1, 2, 3'
ysth
Eric Strom

related questions