Perl: приоритет выражения и оценка - PullRequest
2 голосов
/ 05 марта 2020

У меня есть следующий код:

$codelist = 00;

$OK = '0';
$OK = () = $codelist =~ /$OK/g;

print "$OK\n"; #answer is 2.

Как оценивается выражение $OK = () = $codelist =~ /$OK/g? Каков порядок старшинства?

Ответы [ 3 ]

5 голосов
/ 05 марта 2020

B::Deparse может показать вам приоритет, если вы когда-либо запутались.

$ perl -MO=Deparse,-p -e '$OK = () = "00" =~ /0/g'
($OK = (() = ('00' =~ /0/g)));
-e syntax OK
3 голосов
/ 05 марта 2020

Если вы посмотрите на perldoc perlop, то есть следующая диаграмма приоритетов :

left        terms and list operators (leftward)
left        ->
nonassoc    ++ --
right       **
right       ! ~ \ and unary + and -
left        =~ !~
left        * / % x
left        + - .
left        << >>
nonassoc    named unary operators
nonassoc    < > <= >= lt gt le ge
nonassoc    == != <=> eq ne cmp ~~
left        &
left        | ^
left        &&
left        || //
nonassoc    ..  ...
right       ?:
right       = += -= *= etc. goto last next redo dump
left        , =>
nonassoc    list operators (rightward)
right       not
left        and
left        or xor

Из этой диаграммы мы ищем =~ и =, потому что они единственные операторы, которые у вас есть здесь.

=~ - это более жесткая привязка, поэтому сначала выполняется оценка $OK = () = ($codelist =~ /$OK/g);

Затем = в left порядке ...

($OK = () = ($codelist =~ /$OK/g));
($OK = (() = ($codelist =~ /$OK/g)));

Другим полезным инструментом, упомянутым в других ответах, является B::Deparse с опцией -p. Тем не менее, это хорошая идея, чтобы ознакомиться с приведенной выше таблицей или хотя бы знать, где на нее ссылаться.

В качестве примечания: =()= - довольно распространенная идиома, настолько, что она имеет запись в дистрибутиве perlsecret в качестве секретного оператора "Goatse" (не Google это) или "Saturn"; он по существу используется для принудительного отображения контекста списка с правой стороны, обычно для возврата счетчика (поскольку левая сторона является скаляром).

1 голос
/ 05 марта 2020

Я предполагаю, что ваш пример кода начинается с

$codelist = '00';

Код

$OK = () = $codelist =~ /$OK/g;

сначала сопоставляет $ codelist с 0 глобально , поэтому он возвращает ВСЕ совпадения. Но это только правда, когда вызывается в контексте списка. Иначе, это только возвратило бы, соответствует ли это или нет. Трюк присваивания с

$OK= () = ...

устанавливает контекст списка для оценки и оценивает возвращенный массив в скалярном контексте (что приводит к количеству элементов).

Так что, когда вы удалите / g в совпадении или () = в задании, которое вы получите 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...