问题
I was just reading the secret pseudo-constants, namely the Space fleet constant
<=><=><=> Space fleet 0
This seems to be because the outer <=>
is doing something I don't understand. My question is why does
my $foo = <=>;
Set $foo
to =
? Other non-alphanumerics seem to work too,
my $foo = <=>;
my $foo = <->;
my $foo = </>;
But, alphanumerics don't...
my $foo = <a>;
Moreover, the perlsecret pod is confusing to me,
Even though it looks like a sequence of three spaceship operators, only the middle ship is an actual spaceship. The two outer "spaceships" are actually calls to
glob("=")
.
It doesn't seem to be the case either, as I can't make sense as to why, glob("=")
would return =
, but glob("a")
would return undef
-- even if there is a file called a
in the current working directory.
What is Perl doing in both of these cases? I assume it's falling back to a literal if the thing inside the <>
isn't an alphanumeric -- is that behavior supported?
回答1:
Where an expression is expected, Perl picks the first of the following that applies:
<>
is short for<ARGV>
<<>>
is a "safe" version of<>
(uses 3-arg open instead of 2-arg open)<<
is otherwise the start of a here-doc operator.<IDENTIFIER>
is short for readline(IDENTIFIER)<...>
is otherwise short for glob(qq<...>)
Where an infix or postfix operator is expected, Perl picks the first of the following that applies:
<=>
is the numerical comparison operator.<=
is otherwise the numerical less-than-or-equal operator.<<
is the shift operator.<
is otherwise the numerical less-than operator.
(The last three might not be relevant here. I added them to cover everything starting with <
.)
So,
<=><=><=>
is short for
glob(qq<=>) <=> glob(qq<=>)
which can be written
glob("=") <=> glob("=")
or
"=" <=> "="
since a glob pattern with no special glob characters simply returns the pattern.
It warns "isn't numeric" twice and evaluates to zero.
my $foo = <=>;
is short for
my $foo = glob(qq<=>);
which can be written
my $foo = glob("=");
or
my $foo = "=";
my $foo = <a>;
is short for
my $foo = readline(a);
It warns "used only once: possible typo" if there are no other mentions of
*a
.It warns "on unopened filehandle" if you haven't previously opened
a
as a file handle.
回答2:
When in doubt check with -MO=Deparse
:
$ perl -MO=Deparse -e '$foo = <=>'
use File::Glob ();
$foo = glob('=');
Spacefleet gives 0 as both operands to <=>
are equal,
perl -MO=Deparse -e '$foo = <=><=><=>'
use File::Glob ();
$foo = glob('=') <=> glob('=');
回答3:
my $foo = <=>;
my $foo = <->;
my $foo = </>;
These are all interpreted as uses of glob. Since there are no *
, ?
, or […]
constructions in their arguments, they expand to the text passed in.
my $foo = <a>;
This is interpreted as reading one line from a file handle called a
.
Anyways. <=><=><=>
behaves like glob("=") <=> glob("=")
. Since both sides evaluate to "="
, they're equal, and the comparison returns 0.
回答4:
I think I see what's going on,
glob("*asdf*");
Will return only files that have the string asdf
in their name because the metacharacter expansion tests for file-exists. However,
glob("asdf");
will always return asdf
, regardless of the status of the file. By extension <=>
lackinging a metacharacter will also return '='
.
来源:https://stackoverflow.com/questions/51203023/perl-lexer-why-does-eq-in-the-context-of