2 votes

Perl : Le retour de la valeur d'une méthode objet ne déclenche pas l'instruction "if".

J'essaie de déboguer mon programme, et je veux envoyer des notifications à un observateur s'il y a des notifications à recevoir.

J'ai une méthode Notify qui renvoie une liste de fichiers que l'observateur veut suivre. Mon debug La routine est juste là pour m'aider à déboguer mon programme.

Ça marche. Je vois le deuxième debug la routine d'impression de la valeur :

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);
    }

}

Cependant, cela échoue :

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);
    }

}

La différence entre la première et la seconde : dans la première, je renvoie $watcher->Notify à un tableau @foo et tester sur @foo . Dans la seconde, je teste sur la valeur de retour de $watcher->Notify .

La sous-routine Notify ressemble à ceci :

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}};
}

Attendez une seconde...

Ok, en tapant cette question, j'ai réalisé que quand je disais if ($watcher->Notify) je retourne dans un contexte scalaire, et quand je dis @foo = $watcher->Notify je retourne dans un contexte de liste. D'autres tests avec ceci :

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);
    }

}

Montré que $foo était nulle. Je change ma méthode pour :

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}};
   }
}

Cela fonctionne maintenant. (La méthode vérifie maintenant si je veux un tableau et si je ne le veux pas, elle retourne un scalaire explicite).

La question est de savoir pourquoi.

Je pensais que si je renvoyais un tableau dans un contexte scalaire, Perl devrait soit faire automatiquement un scalar pour moi (et retourner le nombre d'éléments dans le tableau) ou au moins joindre tous les éléments du tableau avec $" comme séparateur. (J'ai supposé le premier, mais le second aurait également fonctionné).

Par exemple :

#! /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";

s'imprime :

Bar = 4   @foo = this that the other

Où ai-je fait fausse route ? (Je veux dire, en dehors de la vente de toutes mes actions Apple lorsque le prix est monté jusqu'à 40 dollars par action).

3voto

cjm Points 44090

Tu ne retournais pas un tableau. Tu retournais le résultat de sort appelé dans un contexte scalaire. D'après les docs :

Dans un contexte scalaire, le comportement de sort() est indéfinie.

Ce qui veut dire qu'il peut faire tout ce qu'il veut, y compris retourner undef .

2voto

MisterEd Points 1265

Parce que vous retourniez le résultat de sort dans un contexte scalaire :

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

Dans un contexte de liste, cela trie la LISTE et renvoie la liste triée. valeur. Dans un contexte scalaire, le comportement de sort() est indéfini.

EDIT : Si vous ne voulez pas utiliser wantarray que vous pourriez changer :

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

à :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X