2017-06-19 3 views
-1

Perl noob.Perl: renvoie un tableau du sous-programme .pm

Je n'arrive pas à comprendre comment renvoyer une valeur de tableau à partir d'un sous-programme dans un fichier .pm.

fichier .pl a les éléments suivants:

print "Enter your first and last name.\n"; 
    chomp(my $fullname = <STDIN>); #input is 'testing this' all lower case 

Jhusbands::Loginpass->check_name($fullname); 

print "$fullname\n"; 

.pm comprend la sous-routine suivante:

sub check_name { 
    my $class = shift; 
    if ($_[0] =~ /^\w+\s+\w+$/) { 
     @_ = split(/ /, $_[0]); 

      foreach $_ (@_) { 
       $_ = ucfirst lc for @_; 
       @_ = join(" ", @_); 
       print Dumper(@_) . "\n"; 
       return @_; 
      } 
     } 
} 

Je prends le nom, la vérification pour seulement le premier et le dernier (je vais obtenir à d'autres déclarations plus tard), en le divisant, en corrigeant le cas, et en rejoignant à nouveau. Le tableau final est affiché comme:

    $VAR1 = 'Testing This'; 

Donc, il semble fonctionner jusqu'à présent. Cependant, le vale de retour pour fullname $ dans le fichier .pl affiche le minuscules:

    testing this 

Pourquoi est-il ne prend pas la variable corrigée en majuscules qui affiche tombereau comme la dernière itération de tableau?

+0

Vous supprimez la valeur de retour dans .pl. Vous devez attribuer à quelque chose. – toolic

+0

vous revenez un de votre sous mais ne le stockez nulle part. –

+0

Aussi, que 'foreach $ _ (@_) {...}' devrait être remplacé par juste '...'. – ikegami

Répondre

3

Vous n'attribuez le retour à rien. En outre, le sous manipule @_ ce qu'il ne devrait pas faire, à moins qu'il y ait de grands et directs avantages à cela. Il peut également être simplifié

sub check_name { 
    my ($class, $name) = @_; 

    if ($name =~ /^\w+\s+\w+$/) { 
     return join ' ', map { ucfirst lc } split ' ', $name; 
    } 

    return; 
} 

L'appelant

my $fullname = Jhusbands::Loginpass->check_name($name); 

print "$fullname\n" if $fullname; 

retour d'un sous doit toujours être vérifiée, mais dans ce cas encore plus, car elle traite son entrée conditionnelle.

Notez que j'ai renommé l'entrée en sous (à $name), pour plus de clarté. Si vous souhaitez conserver le même nom, la déclaration de la valeur de retour doit être supprimée.

Si le code dans la sous est destiné à changer le $fullname en écrivant directement à @_ (et vous avez eu pas de retour pour cette raison), qui échoue car après les manipulations spécifiques $_[0] n'est plus à l'argument un alias que a été réussi.

Dans tous les cas, faire cela est très compliqué et inutile. Pour changer directement l'argument, passez-le comme référence et écrivez-lui. Cependant, il est probablement beaucoup plus clair et moins sujet à l'erreur de retourner le résultat.


Il convient de noter que le nom ci-dessus « traitement » se heurte aux problèmes standard avec traitement des noms, en raison de leur variété déconcertante. Si cela doit être complet, l'analyse syntaxique du nom doit être envoyée à une bibliothèque (ou une procédure) arrondie qui peut gérer la dirersité possible.

Merci à ikegami pour commentaires avoir soulevé cette question avec des exemples, ainsi que d'une manière plus directe:

$name =~ s/(\w+)/\u\L$1/g; 
return $name; 

qui, avec /r introduit dans v5.14 peut être écrit comme

return $name =~ s/(\w+)/\u\L$1/gr; 

Si $name n'a pas de mot-caractères (\w) et il n'y a pas de match ce retourne la même chaîne.

+0

Vous me battez à la * exacte * même solution par une seconde (sauf que je renvoie «$ name» si le «si» ne correspond pas;) ++ – stevieb

+0

De toute façon, ils tous clobber 'Foo LeBlanc',' Bar von Braun', 'Baz Hansen-Sinfield', etc. – ikegami

+0

@ikegami Merci, ajouté à la réponse – zdim