问题
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
aas 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