2015-03-28 5 views
0

Почему приведенный ниже код не возвращает какой-либо результат? Я ожидаю, что он распечатает «Содержит».Почему я не получаю выход из этого короткого сценария Perl?

sub is_member { 
    my ($x, @list) = @_; 
    foreach (@list) { 
     if ($x eq $_) {"contains"} else {"doesn't contain"} 
     } 
    } 

my @a = qw(apple x orange but so nos how dod to it a b c); 
print is_member("apple",@a)."\n"; 

Как ниже кода просто прекрасно работать, выводя "является палиндром"

sub is_palindrome { 
    my ($x) = @_; 
    if ($x eq reverse($x)){"is palindrome"} else {"Not a palindrome"} 
    } 
print is_palindrome("radar")."\n"; 

ответ

6

Этот код:

if ($x eq $_) {"contains"} else {"doesn't contain"} 

не печатает или ничего возвращать. Он оценивает две константы, но это все. Я удивлен, что нет жалобы на недостающие точки с запятой. И отступы эксцентричны.

Вы, вероятно, хотите что-то больше, как:

sub is_member 
{ 
    my ($x, @list) = @_; 
    foreach (@list) 
    { 
     return "contains" if ($x eq $_); 
    } 
    return "doesn't contain"; 
} 
+0

Я думаю, что синтаксис верен, он по умолчанию возвращает значение.Приведенный ниже код просто отлично работает и печатает «палиндром» 'sub is_palindrome { my ($ x) = @_; if ($ x eq reverse ($ x)) {"is palindrome"} else {"Не палиндром"} } print is_palindrome ("radar"). "\ N"; ' – garg10may

+4

Если вы любите жить опасно , не жалуйтесь, когда дела идут не так. И не отправляйте мне код для проверки кода - я буду отклонять его каждый раз. В контексте вашего кода, если вы получили что-либо возвращенное, оно будет «не содержать», потому что последняя итерация цикла оценивается как false, когда ключ, который вы ищете, является «яблоком». Вам нужно закончить цикл раньше или сделать явный возврат. Использование неявного возврата является липким Perl и ненадежным для загрузки. –

+0

thx, используя (return "contains";) отлично работает, так как это происходило по всему циклу, последний элемент не соответствует, и он ничего не печатал. – garg10may

2

for петли не имеют возвращаемого значения. В is_palindrome оператор if оценивается сам по себе, что неявно создает возвращаемое значение для подпрограммы.

В случае цикла for, даже если последнее выражение, вычисленное внутри цикла for, стало возвратным значением, последнее проведенное сравнение "apple" eq "c" будет ложным.

Если вы хотите выполнить тест с использованием петли for, вам необходимо будет exit the loop early. Но в Perl grep - это встроенный способ проверить, удовлетворяют ли элементы списка условием.

my $result = (grep $_ eq $x, @list) ? "contains" : "does not contain"; 
print "'@list' $result $x\n"; 

Если вы заинтересованы только в существовании определенного элемента, List::MoreUtils::any и List::MoreUtils::first_index обеспечивают преимущества в производительности в случае, если список длинный.

conditional operator, $cond ? $t : $f, более полезен для записи компактных условных выражений, чем попытка установить оператор if на одной строке с фигурными скобками и всеми.

0

, чтобы уточнить возвращаемые значения subs, по умолчанию Perl возвращает значение оценки последнего выражения в sub ... если оно не находится в цикле. от perldoc:

Если нет возврата не будет найден, и если последнее утверждение является выражение, его значение возвращается. Если последний оператор представляет собой структуру управления циклом как foreach или некоторое время, возвращаемое значение не указывается. Пустое подпункт возвращает пустой список.

но, как заявили другие, вы всегда должны использовать return, если вы возвращаете что угодно, как для удобочитаемости, так и для стабильности.

Это также так, что ваш дополнительный элемент не нужен. grep вернет 0 или 1 в скалярном контексте (который можно использовать как логическое) или новый массив совпадающих значений в контексте массива; ex:

my @a = qw(apple x orange but so nos how dod to it a b c); 
print "found" if grep /^orange$/, @a; # prints "found" 
my @b = grep length > 3, @a; 
print "@b" # prints "apple orange"