Почему вызов print в подпрограмме добавляет 1 к строке? - PullRequest
1 голос
/ 31 октября 2010

Я создал следующий пол подпрограммы для случайной печати строки MALE или FEMALE. Когда вызывается подпрограмма, команда печати ставит суффикс «1» в конце строки. См. Пример кода и вывод ниже:

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

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

Обратите внимание, что суффикс "1" к "MALE" ИЛИ "FEMALE"

ВЫХОД:

FEMALE1
FEMALE1
MALE  1
MALE  1
FEMALE1
MALE  1

Я использую perl v5.8.9 v5.8.9, созданный для MSWin32-x86-multi-thread

Binary build 826 [290470] provided by ActiveState <a href="http://www.ActiveState.com" rel="nofollow">http://www.ActiveState.com</a> Built May 24 2009 09:21:05

Ответы [ 4 ]

14 голосов
/ 31 октября 2010
print &gender

вызывает функцию пола и печатает то, что возвращает. Сам пол, как последнее, что он делает в любой ветке, печатает строку. Неявно, он возвращает результат последнего выражения в нем (печать "MALE" или печать "FEMALE"), и print, когда это успешно, возвращает 1.

Так что либо сделайте это:

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

или это:

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

Также обратите внимание, что &gender, с & без скобок, является особой формой вызова функции, которая обычно не является тем, что люди хотят использовать; или удалите & или добавьте пустые скобки к вашему звонку.

Я также исправил тест if, чтобы он возвращал мужчин 50% времени и женщин 50% времени вместо 49% и 51% соответственно.

8 голосов
/ 31 октября 2010

Давайте разберемся с вашим кодом:

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

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

Итак, что я сделал?

Первый:

  1. Подставка gender не должна вызываться с & и без паренов. Это вызывает подпрограмму с аргументами, передаваемыми вызывающей стороне. Это удобно, когда у вас есть куча общего кода для очистки аргументов. Но это нежелательно или необходимо здесь.
  2. Я помещаю подпрограмму после другого кода, потому что мне нравится читать мой код с высокого уровня на конкретный - противоположность того, как С заставляет вас организовывать вещи. Мне не нравится читать мой код снизу вверх, поэтому я сделал это таким образом. Это чисто личное предпочтение. Делай то, что делает тебя счастливым. Или, если вам нужно работать с другими, следуйте общепринятому стандарту.
  3. Я сократил foreach до for. Они делают одно и то же, один берет меньше персонажей.
  4. Я использовал for в качестве модификатора оператора. Другими словами, я взял простое утверждение print $_, "\n"; и прикрепил for к концу. Для простых задач это лучше, чем использование блока. Опять же, это мое мнение. Некоторые люди осуждают модификаторы операторов как зло и не приветствуются. Если вы решили использовать их, сделайте это просто. YMMV.
  5. Я избавился от лишней ненужной печати ysth упомянутой.
  6. Вместо использования большого блока if / else я использовал троичный оператор (ОК, на самом деле это просто троичный оператор, но люди называют его троичный оператор). Он вычисляет значение теста и в зависимости от логического значения теста возвращает результат одним из двух выражений. Это удобно, когда вам нужна логика if / else в назначении.
2 голосов
/ 01 ноября 2010

Без явного return саб Perl вернет последнее оцененное значение.gender возвращает 1, потому что в обоих путях выполнения он вызывает print, который возвращает 1.

Вы должны либо gender вернуть строку, которую вызывающая сторона затем print сgender должен выполнить печать, а вызывающий - ничего не делать с возвращаемым значением.

0 голосов
/ 01 ноября 2010

Спасибо всем за помощь в этом. Я нашел способ сделать диаграмму, которую хотел. Вот как я наконец это сделал;

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 

Создает хороший вывод:

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
...