为什么在子例程中调用print会在字符串中附加1?

Rat*_*dey 1 printing perl return-value subroutine

我创建了以下子例程性别来随机打印字符串MALE或FEMALE.调用子例程时,print命令在字符串末尾加上"1"后缀.请参阅下面的示例代码和输出:

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

foreach (1..5) {
    print &gender, "\n"; 
} 
Run Code Online (Sandbox Code Playgroud)

注意"MALE"或"FEMALE"后缀为"1"

OUTPUT:

FEMALE1
FEMALE1
MALE  1
MALE  1
FEMALE1
MALE  1
Run Code Online (Sandbox Code Playgroud)

我正在使用perl v5.8.9 v5.8.9内置的MSWin32-x86多线程

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

yst*_*sth 14

print &gender
Run Code Online (Sandbox Code Playgroud)

调用性别功能并打印它返回的内容.性别本身,作为它在任一分支中做的最后一件事,打印一个字符串.隐式地,它返回其中最后一个表达式的结果(打印"MALE"或打印"FEMALE"),并且当成功时,打印返回1.

所以要么这样做:

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

或这个:

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

另外,请注意&gender,使用&但没有括号,是一种特殊形式的函数调用,通常不是人们的意思; 要么删除&,要么在您的通话中添加空括号.

我还纠正了if测试,50%的时间返回男性,50%的时间返回女性,而不是49%和51%.

  • 完全无条件地完全放弃.您应该在现代Perl代码中触摸的唯一常见情况是在参考子例程时.(*有*其他用途,但它们很模糊.) (2认同)

dao*_*oad 8

让我们的代码习惯:

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

sub gender {
    return  int rand(100) > 50 ? 'MALE' : 'FEMALE';
}
Run Code Online (Sandbox Code Playgroud)

那么,我做了什么?

第一:

  1. gender子不应与被称为&无括号.这将调用传递给其调用者的参数的子例程.当你有一堆常见的参数清理代码时,这很方便.但这里不可取或不需要.
  2. 我将sub放在其他代码之后,因为我喜欢将我的代码从高级别读取到特定级别 - 这与C强制组织事物的方式相反.我不喜欢自下而上阅读我的代码,所以我这样做了.这纯粹是个人偏好.做任何让你开心的事.或者,如果您必须与他人合作,请遵循您已达成一致的标准.
  3. 我缩短foreachfor.他们做同样的事情,一个人少.
  4. 我用作for语句修饰符.换句话说,我做了一个简单的陈述print $_, "\n";并将其添加for到最后.对于简单的任务,它比使用块更好.再次,这是我的意见.有些人将声明修饰符解密为邪恶且不受欢迎.如果您决定使用它们,请保持简单.因人而异.
  5. 我摆脱了额外的不必要的打印YSTH提及.
  6. 而不是使用一个大的if/else块的,我用了三元运算符(好吧,这真的只是一个三元运算符,但人们叫它三元运算符).它计算测试值,并根据测试的布尔值,返回两个表达式中的一个结果.当你想要赋值中的if/else逻辑时,它很方便.