Why are leading-hyphen options permitted on `use` lines without fat comma and with strict?
Asked Answered
B

2

5

Why is the following use line legal Perl syntax? (Adapted from the POD for parent; tested on Perl 5.26.2 x64 on Cygwin.)

package MyHash;
use strict;
use Tie::Hash;
use parent -norequire, "Tie::StdHash";
       #   ^^^^^^^^^^ A bareword with nothing to protect it!

Under -MO=Deparse, the use line becomes

use parent ('-norequire', 'Tie::StdHash');

but I can't tell from the use docs where the quoting on -norequire comes from.

  • If use strict were not in force, I would understand it. The bareword norequire would become the string "norequire", the unary minus would turn that string into "-bareword", and the resulting string would go into the use import list. For example:

    package MyHash;
    use Tie::Hash;
    use parent -norequire, "Tie::StdHash";
    
  • Similarly, if there were a fat comma, I would understand it. -foo => bar becomes "-foo", bar because => turns foo into "foo", and then the unary minus works its magic again. For example:

    package MyHash;
    use strict;
    use Tie::Hash;
    use parent -norequire => "Tie::StdHash";
    

Both of those examples produce the same deparse for the use line. However, both have quoting that the original example does not. What am I missing that makes the original example (with strict, without =>) legal? Thanks!

Beckybecloud answered 10/12, 2018 at 14:9 Comment(0)
A
5

You already cited perldoc perlop, but it is relevant here.

Unary - performs arithmetic negation if the operand is numeric, including any string that looks like a number. If the operand is an identifier, a string consisting of a minus sign concatenated with the identifier is returned. ... One effect of these rules is that -bareword is equivalent to the string "-bareword".

This behavior of the unary minus operator is applied to the bareword before the strict checks are applied. Therefore, unary minus is a kind of quoting operator that also works in strict mode.

Similarly, barewords as the invocant in method invocation do not need to be quoted as long as they are not a function call:

Foo->bar;    # 'Foo'->bar(); --- but only if no sub Foo exists
print->bar;  # print($_)->bar();

However, the unary minus behaviour seems to be due to constant folding, not due to a special case in the parser. For example, this code

use strict;
0 ? foo : bar;

will only complain about the bareword "bar" being disallowed, suggesting that the bareword check happens very late during parsing and compilation. In the unary minus case, the bareword will already have been constant-folded into a proper string value at that point, and no bareword remains visible.

While this is arguably buggy, it is also impossible to change without breaking backwards compatibility – and this behaviour is used by many modules such as use parent to communicate options. Compare also similar idioms on command line interfaces, where options usually begin with a dash.

Alumna answered 10/12, 2018 at 14:40 Comment(2)
barewords as the target of method invocations should be quoted. Foo->bar is not 'Foo'->bar if a sub Foo exists, it is Foo()->bar. You should use Foo::->bar or 'Foo'->bar.Shrieval
also note -Foo'Bar becomes "-Foo::Bar" - but unlike -Foo::Bar, gives a bareword error unless package Foo exists. this (unlike the basic well documented concept of - implicitly quoting) is arguably buggyShrieval
H
1

From perlop

Symbolic Unary Operators

Unary "-" performs arithmetic negation if the operand is numeric, including any string that looks like a number. If the operand is an identifier, a string consisting of a minus sign concatenated with the identifier is returned. Otherwise, if the string starts with a plus or minus, a string starting with the opposite sign is returned. One effect of these rules is that -bareword is equivalent to the string "-bareword". If, however, the string begins with a non-alphabetic character (excluding "+" or "-"), Perl will attempt to convert the string to a numeric and the arithmetic negation is performed. If the string cannot be cleanly converted to a numeric, Perl will give the warning Argument "the string" isn't numeric in negation (-) at ....

So because of the rules of Perl parsing -name is treated as "-name" even under use strict

Heilman answered 10/12, 2018 at 14:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.