Perl lexer: why does “<=>” eq “=” in the context of <=><=><=>?

会有一股神秘感。 提交于 2019-12-23 07:33:11

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!