2010-10-31 2 views
1

J'ai créé le sous-programme suivant pour imprimer de façon aléatoire la chaîne MALE ou FEMALE. Lorsque le sous-programme est invoqué, la commande d'impression attribue un "1" à la fin de la chaîne. Voir l'exemple de code et la sortie ci-dessous:Pourquoi l'invocation de l'impression dans un sous-programme ajoute-t-elle 1 à la chaîne?

sub gender { 
    if ((int rand(100)) >50) { 
     print "MALE "; 
    } 
    else { 
     print "FEMALE"; 
    } 
} 

foreach (1..5) { 
    print &gender, "\n"; 
} 

avis "1" est ajouté à "mâle" ou "Femmes"

SORTIE:

FEMALE1 
FEMALE1 
MALE 1 
MALE 1 
FEMALE1 
MALE 1 

J'utilise perl v5.8.9 v5.8.9 construit pour MSWin32 -x86-multi-thread

Binary build 826 [290470] provided by ActiveState http://www.ActiveState.com Built May 24 2009 09:21:05

Répondre

14
print &gender 

appelle la fonction de genre et affiche ce qu'elle renvoie. le genre lui-même, comme la dernière chose qu'il fait dans chaque branche, imprime une chaîne. Implicitement, il renvoie le résultat de la dernière expression (le print « mâle » ou imprimer « femelle »), et l'impression, quand elle réussit, renvoie 1.

Donc, soit cela:

sub gender { if (rand(100) >= 50) {print "MALE ";} else {print "FEMALE";}} 
foreach (1..5) { &gender(); print "\n"; } 

ou ceci:

sub gender { if (rand(100) >= 50) {return "MALE ";} else {return "FEMALE";}} 
foreach (1..5) { print &gender(), "\n"; } 

en outre, notez que &gender, avec & mais sans parenthèses, est une forme particulière d'invocation de fonction qui est généralement pas ce que les gens veulent dire à utiliser; soit supprimez & ou ajoutez des parenthèses vides à votre appel.

J'ai également corrigé le test if pour retourner le mâle 50% du temps et la femelle 50% du temps, au lieu de 49% et 51% respectivement.

+0

ou tout simplement tomber entre parenthèses puisque la sous a été déclarée avant l'appel. La meilleure pratique est cependant d'utiliser les parenthèses vides de toute façon – mfontani

+2

Déposez le & complètement et inconditionnellement. Le seul cas courant où vous devriez toucher & dans un code Perl moderne est de prendre une référence à un sous-programme. (Il y a * d'autres utilisations, mais elles sont obscures.) – Porculus

+0

Ignorer les prototypes. Yay. * bâillement * –

8

Obtenons idiomatiques avec votre code:

print gender(), "\n" 
    for 1..5; 

sub gender { 
    return int rand(100) > 50 ? 'MALE' : 'FEMALE'; 
} 

Alors, qu'est-ce que je fais?

Première:

  1. Le sous gender ne doit pas être appelé avec l'& et sans parens. Cela appelle la sous-routine sur les arguments passés à son appelant. C'est pratique quand vous avez un tas de code d'assainissement commun. Mais ce n'est pas souhaitable ou nécessaire ici.
  2. Je mets le sub après l'autre code parce que j'aime lire mon code de haut niveau à spécifique - le contraire de la façon dont C vous oblige à organiser les choses. Je n'aime pas lire mon code de bas en haut, alors je l'ai fait de cette façon. C'est purement une préférence personnelle. Fais tout ce qui te rend heureux. Ou si vous devez travailler avec d'autres, suivez la norme que vous avez acceptée. J'ai raccourci foreach à for. Ils font exactement la même chose, on prend moins de caractères. J'ai utilisé for comme modificateur d'instruction. En d'autres termes, j'ai pris une déclaration simple print $_, "\n"; et viré le for sur la fin. Pour les tâches simples, il est plus agréable que d'utiliser un bloc. Encore une fois, c'est mon opinion.Certaines personnes décrient les modificateurs d'instruction comme mal et importun. Si vous décidez de les utiliser, restez simple. YMMV.
  3. Je me suis débarrassé de l'impression supplémentaire inutile ysth mentionné.
  4. Au lieu d'utiliser un grand si/bloc d'autre, j'utilisé l'opérateur ternaire (OK, il est vraiment juste un opérateur ternaire, mais les gens appellent l'opérateur ternaire). Il calcule une valeur de test et, en fonction de la valeur booléenne du test, renvoie le résultat à l'une des deux expressions. C'est pratique quand vous voulez une logique if/else dans une affectation.
+3

7. .... profit! – ysth

+1

Qu'est-ce que 'int()' pour? – tchrist

+0

L'int ne fait vraiment rien de pratique. Il force un petit changement dans les probabilités - 'int (50.9)' est 50, et donc donne 'FEMALE'. Sans le 'int', 50.9 donne' MALE'. Je suppose que c'est une fonctionnalité involontaire, mais je ne voulais pas changer les probabilités. Peut-être que c'est ce que le numéro 7 est pour. – daotoad

2

Sans return explicite, sous Perl retournera la dernière valeur évaluée. gender renvoie un 1 car dans les deux chemins d'exécution, il appelle print qui retourne un 1.

Vous devez soit être avoir gender retour une chaîne, que l'appelant puis print s, ou ont gender faire l'impression, et ont l'appelant ne faites rien avec la valeur de retour.

0

Merci à tous pour m'avoir aidé. J'ai trouvé un moyen de faire un tableau que je voulais. Voici comment je l'ai finalement fait;

print "GENDER NAME AGE HEIGHT WEIGHT \n"; 
foreach (1..10) {      ## Starting foreach loop 
$age = int(rand(50))+10; 
$height = int (rand(40)) + 50; 
$weight = int (rand (100)) + 100; 
sub randchar4bit {(chr int rand(25)+65).(chr int rand(25)+65). (chr int rand(25)+65).(chr int rand(25)+65)}; 
sub gender { return (int rand(100)>50)? "MALE " : "FEMALE ";} ; 

print gender(), " ", &randchar4bit, " $age  $height  $weight style 1\n"; 
}; ## closing foreach loop 

Il génère une sortie agréable:

GENDER NAME AGE HEIGHT WEIGHT 
FEMALE HHRN 41  67  165 style 1 
MALE  HNMF 27  63  187 style 1 
MALE  NLDB 26  54  165 style 1 
FEMALE REMB 33  71  118 style 1 
MALE  TWEW 10  57  122 style 1 
MALE  OCSC 35  80  168 style 1 
FEMALE TKTR 25  64  179 style 1 
MALE  GMYN 47  73  123 style 1 
MALE  YKUG 50  79  148 style 1 
FEMALE HDFW 47  73  159 style 1 
Questions connexes