Почему в Perl добавляется || умереть на заявлении, заставить его оценивать в скалярном контексте?

Я наконец обнаружил, что мой код оценивался в скалярном контексте, а не в контексте списка, хотя у меня было () вокруг присваивания.

  • 1-й вопрос: почему добавление "|| die ..." к выражению / присваиванию заставляет его оцениваться в скалярном контексте?

  • Во-вторых, есть ли идиома / эквивалент «|| die ....», которая может использоваться при назначении списка?

Вот мой пример кода, демонстрирующий проблему.

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper qw(Dumper);

my $h1 = {
    var => "1",
    bar => "1",
    baz => "1",
};

my $h2 = {
    var => "2",
    bar => "2",
    baz => "2",
};

my $ds;
$ds->{rules} = [$h1,$h2];

print "TEST1\n";
print Dumper($ds);

print "TEST2\n";
my (@processes) = @{$ds->{rules}};
print Dumper(\@processes);
print "@processes\n";

print "TEST3\n";
(@processes) = @{$ds->{rules}} || die "unable to get rules form config.. \n";
print Dumper(\@processes);
print "@processes\n";

Вывод:

TEST2
$VAR1 = [
          {
            'bar' => '1',
            'baz' => '1',
            'var' => '1'
          },
          {
            'bar' => '2',
            'baz' => '2',
            'var' => '2'
          }
        ];
HASH(0x25eea68) HASH(0x260b240) 
TEST3
$VAR1 = [
          2
        ];
2

Сравните ТЕСТ2 и ТЕСТ3. Насколько я могу судить, простое добавление бита || die '.... ' в конец изменяет способ вычисления оператора в скалярном контексте, даже несмотря на то, что у меня есть скобки с левой стороны. Q1: Может быть, я просто тупица, но почему это происходит?

Q2: есть ли идиома / эквивалент «|| die ....», которую можно использовать при назначении списка?


person sparco1500    schedule 24.06.2019    source источник


Ответы (1)


Причина, по которой это вызывает скалярный контекст, заключается в том, что || связывает сильнее, чем =, поэтому

(@processes) = @{$ds->{rules}} || die "unable to get rules form config.. \n";

Анализируется как

(@processes) = (@{$ds->{rules}} || die "unable to get rules form config.. \n");

И || создает логический контекст. Однако perl имеет слабо связывающую версию ||:

(@processes) = @{$ds->{rules}} or die "unable to get rules form config.. \n";

Которая будет проанализирована так, как вы хотите.

person Q the Platypus    schedule 24.06.2019
comment
Спасибо за ответ! Есть ли какой-нибудь учебник / технический документ, объясняющий это? Все материалы, с которыми я столкнулся, не касались этой оговорки. Много лет назад я думаю, что тренер по Perl на курсе рекомендовал всегда использовать || вместо or, но с тех пор я забыл объяснение, почему (если он действительно дал нам его). (на самом деле теперь я вижу, что я использовал или и || как взаимозаменяемые, что, очевидно, очень опасно. Я отредактировал свой вопрос, чтобы показать, что на самом деле делал мой код.) - person sparco1500; 24.06.2019
comment
@ sparco1500 Я отредактировал несколько ссылок на документацию в ответ. - person melpomene; 24.06.2019
comment
@ sparco1500 - Помимо ссылок на документацию, которые были добавлены к ответу, общее практическое правило - использовать || для логических операций; используйте or для управления потоком. То же самое относится к && и and. - person Dave Sherohman; 24.06.2019
comment
@ sparco1500, Обычно используется or для управления потоком (or die, or next, or return и т. д.), а || где-то еще. - person ikegami; 24.06.2019