Perl lexer: почему "<=>" eq "=" в контексте <=> <=> <=>? - PullRequest
0 голосов
/ 06 июля 2018

Я только что прочитал секретные псевдоконстанты, а именно Константа космического флота

<=><=><=>   Space fleet                 0

Кажется, это потому, что внешний <=> делает что-то, чего я не понимаю. Мой вопрос: почему

my $foo = <=>;

Установить $foo на =? Другие не алфавитно-цифровые символы тоже работают,

my $foo = <=>;
my $foo = <->;
my $foo = </>;

Но буквенно-цифровые символы не ...

my $foo = <a>;

Более того, стручок perlsecret сбивает меня с толку ,

Хотя это выглядит как последовательность из трех операторов космического корабля, только средний корабль является настоящим космическим кораблем. Два внешних "космических корабля" на самом деле являются вызовами glob("=").

Похоже, что это не так, поскольку я не могу понять, почему, glob("=") вернул бы =, но glob("a") вернул бы undef - даже если есть файл с именем a в текущем рабочем каталоге.

Что делает Perl в обоих этих случаях? Я предполагаю, что он возвращается к литералу, если вещь внутри <> не является буквенно-цифровой - это поведение поддерживается?

Ответы [ 4 ]

0 голосов
/ 06 июля 2018

Если есть сомнения, уточните с помощью -MO=Deparse:

$ perl -MO=Deparse -e '$foo = <=>'

use File::Glob ();
$foo = glob('=');

Spacefleet дает 0, так как оба операнда равны <=>,

perl -MO=Deparse -e '$foo = <=><=><=>'

use File::Glob ();
$foo = glob('=') <=> glob('=');
0 голосов
/ 06 июля 2018

Мне кажется, я вижу, что происходит,

glob("*asdf*");

Будет возвращать только те файлы, в имени которых есть строка asdf, поскольку тесты расширения метасимвола для файла существуют. Тем не менее,

glob("asdf");

будет всегда возвращать asdf независимо от состояния файла. При расширении <=> без метасимвола также будет возвращено '='.

0 голосов
/ 06 июля 2018

Если ожидается выражение, Perl выбирает первое из следующего:

  • <> это сокращение от <ARGV>
  • <<>> - это «безопасная» версия <> (использует открытие с 3 аргументами вместо открытия с 2 аргументами)
  • << в противном случае является началом операции here-doc .
  • <IDENTIFIER> это сокращение от readline(IDENTIFIER)
  • <...> в противном случае означает glob(qq<...>)

Если ожидается оператор инфикса или постфикса, Perl выбирает первое из следующего:

  • <=> является оператором числового сравнения .
  • <= в противном случае является числовым оператором меньше или равным.
  • << - оператор сдвига.
  • < в противном случае - числовой оператор меньше чем.

(Последние три могут быть здесь неактуальны. Я добавил их, чтобы охватить все, начиная с <.)

Итак,

  • & # x20;

    <=><=><=>
    

    это сокращение от

    glob(qq<=>) <=> glob(qq<=>)
    

    который можно написать

    glob("=") <=> glob("=")
    

    или

    "=" <=> "="
    

    , поскольку шаблон glob без специальных символов glob просто возвращает шаблон.

    Он предупреждает "не является числовым" дважды и оценивается в ноль.

  • & # x20;

    my $foo = <=>;
    

    это сокращение от

    my $foo = glob(qq<=>);
    

    которое можно написать

    my $foo = glob("=");
    

    или

    my $foo = "=";
    
  • & # x20;

    my $foo = <a>;
    

    это сокращение от

    my $foo = readline(a);
    

    Предупреждает «используется только один раз: возможная опечатка», если нет других упоминаний *a.

    Он предупреждает «о неоткрытом дескрипторе файла», если вы ранее не открывали a как дескриптор файла.

0 голосов
/ 06 июля 2018
my $foo = <=>;
my $foo = <->;
my $foo = </>;

Все они интерпретируются как использование glob. Поскольку в их аргументах нет конструкций *, ? или […], они расширяются до переданного текста.

my $foo = <a>;

Это интерпретируется как чтение одной строки из дескриптора файла с именем a.

В любом случае. <=><=><=> ведет себя как glob("=") <=> glob("="). Поскольку обе стороны оценивают "=", они равны, и сравнение возвращает 0.

...