Массив в левой части оператора сопоставления

Обнаружил странное поведение моего скрипта, когда левая часть представляет собой массив:

#!/usr/bin/perl

sub say {
    print @_, "\n";
}


my @arr = ('I', 'am', 'Qiang');
if (@arr =~ /Qiang/) {
    say("1: Match!!!");
} else {
    say("1: No match found");
}

@arr = ('Qiang');
if (@arr =~ /Qiang/) {
    say("2: Match!!!");
} else {
    say("2: No match found");
}

if (('Qiang') =~ /Qiang/) {
    say("3: Match!!!");
} else {
    say("3: No match found");
}
qxu@xqiang-mac-0:~/test$ ./regex_array_match.pl 
1: No match found
2: No match found
3: Match!!!

Код во 2-м и 3-м случаях выглядит одинаково, но результаты разные.

Что должен делать Perl, когда в левой части оператора сопоставления появляется массив?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Оператор =~ оценивает свой левый операнд в скалярном контексте (ему нужна строка).

Массив в скалярном контексте дает количество содержащихся в нем элементов, что в вашем случае равно 3 и 1 соответственно.

Таким образом, условия становятся "3" =~ /Qiang/ и "1" =~ /Qiang/, оба из которых ложны.

Если вы use strict; use warnings; (что вы всегда должны делать), вы увидите следующее предупреждение:

Applying pattern match (m//) to @arr will act on scalar(@arr)

... который perldoc perldiagобъясняет как:

(W misc) The pattern match (//), substitution (s///), and transliteration (tr///) operators work on scalar values. If you apply one of them to an array or a hash, it will convert the array or hash to a scalar value (the length of an array, or the population info of a hash) and then work on that scalar value. This is probably not what you meant to do. See "grep" in perlfunc and "map" in perlfunc for alternatives.


Чтобы проверить, соответствует ли какой-либо элемент массива шаблону регулярного выражения, вы можете использовать grep следующим образом:

my @arr = ('I', 'am', 'Qiang');
if ( grep { /Qiang/ } @arr ) {
    say("At least one match!!!");
} else {
    say("No match found");
}

grep фактически вернет количество совпадающих элементов при оценке в скалярном контексте, поэтому это менее эффективно, чем могло бы быть (он всегда будет проверять каждый элемент массива). Чтобы прекратить проверку после того, как будет найдено первое совпадение, используйте any из списка::Util.

Спасибо, а в третьем случае разве это не массив? Почему в таком случае есть совпадение? Массив стал плоским?

Qiang Xu 10.04.2019 01:53

@QiangXu В третьем случае массива нет. У вас есть простая строка в (лишних) круглых скобках. Это как писать $x = (2 + 2); скобки не нужны, но и вреда они не приносят.

melpomene 10.04.2019 01:55

@QiangXu «массив» — это тип переменной, а не тип значения; круглые скобки не создают массивы. (хотя [] вернет ссылку на анонимный массив, но это совсем другое)

ysth 10.04.2019 02:07

@QiangXu В my @arr = ('I', 'am', 'Qiang'); скобки используются только для переопределения приоритета (по умолчанию = имеет более высокий приоритет, чем ,). В @arr = ('Qiang'); круглые скобки избыточны, и вы могли бы просто написать @arr = 'Qiang';.

melpomene 10.04.2019 02:14

Добавил решение. Не стесняйтесь вернуться.

ikegami 10.04.2019 04:18

@QiangXu, Parens ((...)) не создают списки, тем более массивы. Массивы — это тип переменной, и в ('Qiang') нет переменных. Parens просто влияет на приоритет. ('Qiang') и 'Qiang' оба вычисляют строковый скаляр Qiang независимо от контекста.

ikegami 10.04.2019 04:26

Другие вопросы по теме