Perl: возвращаемое значение метода объекта не запускает оператор if - PullRequest
2 голосов
/ 31 октября 2011

Я пытаюсь отладить свою программу и хочу отправить уведомления наблюдателю, если есть какие-либо уведомления, чтобы получить.

У меня есть метод Notify, который возвращает список файлов, которыенаблюдатель хочет следовать.Моя подпрограмма debug как раз помогает мне отлаживать мою программу.

Это работает.Я вижу вторую debug рутинную распечатку значения:

foreach my $watcher ($watch->Watcher) {
    debug qq(Sending out notifcations for ) . $watcher->User, 2;
    my @foo = $watcher->Notify;
    if (@foo) {
        debug qq(Change list to notify on: ) . join (", " => $watcher->Notify), 3;
        $watch->SendEmail($watcher);
    }

}

Однако, это не удается:

foreach my $watcher ($watch->Watcher) {
    debug qq(Sending out notifcations for ) . $watcher->User, 2;
    if ($watcher->Notify) {
        debug qq(Change list to notify on: ) . join (", " => $watcher->Notify), 3;
        $watch->SendEmail($watcher);
    }

}

Разница между первым и вторым: в первом я возвращаю $watcher->Notify в массив @foo и проверяю на @foo.Во втором я проверяю возвращаемое значение $watcher->Notify.

Подпрограмма Notify выглядит следующим образом:

sub Notify {
    my $self   = shift;
    my $change = shift;

    $self->{CHANGE} = [] if not exists $self->{CHANGE};
    if (defined $change) {
        push @{$self->{CHANGE}}, $change;
    }
    return sort @{$self->{CHANGE}};
}

Подождите секунду ...

Хорошо, когда я набирал этот вопрос, я понял, что когда я говорю if ($watcher->Notify), я возвращаюсь в скалярный контекст, а когда я говорю @foo = $watcher->Notify, я возвращаюсь в контекст списка.Дальнейшее тестирование с этим:

foreach my $watcher ($watch->Watcher) {
    debug qq(Sending out notifcations for ) . $watcher->User, 2;
    my $foo = $watcher->Notify;   #Now a SCALAR and not a LIST
    if ($foo) {
        debug qq(Change list to notify on: ) . join (", " => $watcher->Notify), 3;
        $watch->SendEmail($watcher);
    }

}

Показано, что $foo было нулевым.Изменение моего метода на:

sub Notify {
    my $self   = shift;
    my $change = shift;

    $self->{CHANGE} = [] if not exists $self->{CHANGE};
    if (defined $change) {
        push @{$self->{CHANGE}}, $change;
    }
    if (wantarray) {
       return sort @{$self->{CHANGE}};
    }
    else {
       return scalar @{$self->{CHANGE}};
   }
}

Теперь работает.(Метод теперь проверяет, хочу ли я массив, а если нет, возвращает явный скаляр).

Вопрос в том, почему.

Я подумал, вернул ли я массив в скалярВ контексте Perl должен либо автоматически выполнить для меня scalar (и вернуть количество элементов в массиве), либо, по крайней мере, объединить все элементы в массиве с $" в качестве разделителя.(Я предположил, что первое, но последнее также сработало бы).

Например:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say switch);
use Data::Dumper;

my @foo = qw(this that the other);

my $bar = @foo;

say "Bar = $bar   \@foo = @foo";

распечатывает:

Bar = 4   @foo = this that the other

Где я ошибся?(Я имею в виду, помимо продажи всех моих акций Apple, когда цена поднялась до 40 долларов за акцию).

Ответы [ 2 ]

3 голосов
/ 31 октября 2011

Вы не возвращали массив. Вы возвращали результат sort, вызванный в скалярном контексте. Согласно документам :

В скалярном контексте поведение sort() не определено.

Это означает, что он может делать все, что захочет, включая возвращение undef.

2 голосов
/ 31 октября 2011

Поскольку вы возвращали результат sort в скалярном контексте:

From http://perldoc.perl.org/functions/sort.html:

В контексте списка это сортирует LIST и возвращает отсортированное значение списка,В скалярном контексте поведение sort () не определено.

EDIT: если вы не хотите использовать wantarray, вы можете изменить:

return sort @{$self->{CHANGE}};

на:

return @{ [sort @{$self->{CHANGE}}] };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...