Reputation: 83
I have created the following subroutine gender to randomly print string MALE or FEMALE. When subroutine is invoked, the print command suffixes a "1" at the end of the string. See the sample code and output below:
sub gender {
if ( (int rand(100)) >50) {
print "MALE ";
}
else {
print "FEMALE";
}
}
foreach (1..5) {
print &gender, "\n";
}
Notice a "1" is suffixed to "MALE" OR "FEMALE"
OUTPUT:
FEMALE1
FEMALE1
MALE 1
MALE 1
FEMALE1
MALE 1
I am using perl v5.8.9 v5.8.9
built for MSWin32-x86-multi-thread
Binary build 826 [290470] provided by ActiveState http://www.ActiveState.com Built May 24 2009 09:21:05
Upvotes: 1
Views: 818
Reputation: 83
Thank You everyone for helping me out with this. I found a way to make a chart I wanted. Here is how I finally did it;
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
It generates a nice output:
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
Upvotes: 0
Reputation: 93715
Without an explicit return
, the Perl sub will return the last evaluated value. gender
returns a 1 because in both execution paths, it calls print
which returns a 1.
You should either be having gender
return a string, which the caller then print
s, or have gender
do the printing, and have the caller not do anything with the return value.
Upvotes: 2
Reputation: 98398
print &gender
calls the gender function and prints what it returns. gender itself, as the last thing it does in either branch, prints a string. Implicitly, it returns the result of the last expression in it (the print "MALE" or print "FEMALE"), and print, when it succeeds, returns 1.
So either do this:
sub gender { if ( rand(100) >= 50 ) {print "MALE ";} else {print "FEMALE";}}
foreach (1..5) { &gender(); print "\n"; }
or this:
sub gender { if ( rand(100) >= 50 ) {return "MALE ";} else {return "FEMALE";}}
foreach (1..5) { print &gender(), "\n"; }
Also, note that &gender
, with & but without parentheses, is a special form of function invocation that isn't usually what people mean to use; either drop the & or add empty parentheses to your call.
I've also corrected the if test to return male 50% of the time and female 50% of the time, instead of 49% and 51% respectively.
Upvotes: 14
Reputation: 27183
Let's get idiomatic with your code:
print gender(), "\n"
for 1..5;
sub gender {
return int rand(100) > 50 ? 'MALE' : 'FEMALE';
}
So, what did I do?
First:
gender
sub should not be called with the &
and no parens. This invokes the subroutine on the arguments passed to its caller. This is handy when you have a bunch of common argument sanitizing code. But it is not desirable or needed here.foreach
to for
. They do exactly the same thing, one takes fewer characters.for
as a statement modifier. In other words I took a simple statement print $_, "\n";
and tacked the for
onto the end. For simple tasks it is nicer than using a block. Again, this is my opinion. Some people decry statement modifiers as evil and unwelcome. If you decide to use them, keep it simple. YMMV.Upvotes: 8