I’m trying to debug my program, and I want to send out notifications to a watcher if there are any notifications to get.
I have a method Notify that returns a list of files that the watcher wants to follow. My debug routine is just there to help me debug my program.
This works. I see the second debug routine printing out the value:
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);
}
}
However, this fails:
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);
}
}
The difference between the first and second: In the first, I return $watcher->Notify to an array @foo and test on @foo. In the second, I test on the return value of $watcher->Notify.
The Notify subroutine looks like this:
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}};
}
Wait a second…
Okay, as I was typing this question out, I realized that when I say if ($watcher->Notify), I am returning into a scalar context, and when I say @foo = $watcher->Notify, I’m returning into a list context. Further testing with this:
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);
}
}
Showed that $foo was null. Changing my method to:
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}};
}
}
Now works. (Method now checks if I want an array and if I don’t, it returns an explicit scalar).
The question is why.
I thought if I returned an array into a scalar context, Perl should either be automatically doing a scalar for me (and return the number of items in the array) or at least join all elements in the array with $" as a separator. (I assumed the first, but the latter would have also worked).
For example:
#! /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";
prints out:
Bar = 4 @foo = this that the other
Where did I go wrong? (I mean, besides selling all of my Apple stock when the price went all the way up to $40/share).
You weren’t returning an array. You were returning the result of
sortcalled in scalar context. According to the docs:Which means it gets to do anything it wants, including returning
undef.