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!
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.