Что означает "0, но true" в Perl?



может кто-нибудь объяснить, что именно строка "0 но true" означает в Perl? Насколько я понимаю, он равен нулю в целочисленном сравнении, но оценивается как true при использовании в качестве булева. Это правильно? Это нормальное поведение языка или это специальная строка рассматривается как особый случай в переводчик?

712   14  

14 ответов:

это нормальное поведение языка. Цитируя perlsyn manpage:

количество 0 строки '0' и "" пустой список () и undef все false в логическом контексте. Все остальные значения-true. Отрицание истинного значения ! или not возвращает специальное значение false. При вычислении в виде строки он обрабатывается как "", а как число, это рассматриваться как 0.

из-за этого должен быть способ вернуться 0 от системного вызова, который ожидает возврата 0 как (успешное) возвращаемое значение, и оставить способ сигнализировать случай отказа, фактически возвращая ложное значение. "0 but true" служит этой цели.

потому что он жестко закодирован в ядре Perl, чтобы рассматривать его как число. Это хак, чтобы сделать соглашения Perl и ioctlусловности играют вместе; от perldoc -f ioctl:

возвращаемое значение ioctlfcntl) следующим образом:

if OS returns:      then Perl returns:

    -1              undefined value
     0              string "0 but true"
anything else       that number
на Perl возвращает true в случае успеха и false в случае возникновения ошибки, пока вы еще можно легко определить фактическое значение, возвращаемое операционная система:
$retval = ioctl(...) || -1;
printf "System returned %d\n", $retval;

специальная строка "0 but true" освобождается от -w жалобы о неправильных числовых преобразованиях.

В дополнение к тому, что говорили другие,"0 but true" является специальным случаем в том, что он не предупреждает в числовом контексте:

$ perl -wle 'print "0 but true" + 3'
3
$ perl -wle 'print "0 but crazy" + 3'
Argument "0 but crazy" isn't numeric in addition (+) at -e line 1.
3

значение 0 but true является частным случаем в Perl. Хотя для ваших простых смертных глаз это не похоже на число, мудрый и всезнающий Перл понимает, что это действительно число.

это связано с тем, что когда подпрограммы в Perl возвращает значение 0, предполагается, что процедура не удалась или возвращено значение false.

представьте себе, у меня есть подпрограмма, которая возвращает сумму двух чисел:

die "You can only add two numbers\n" if (not add(3, -2));
die "You can only add two numbers\n" if (not add("cow", "dog"));
die "You can only add two numbers\n" if (not add(3, -3));

первое утверждение не умрет, потому что подпрограмма возвращает 1. Это хорошо. Второй оператор умрет, потому что подпрограмма не сможет добавить корова до собака.

и третье заявление?

хммм, я могу добавить 3 до -3. Я просто получаю 0, но тогда моя программа умрет, даже если add подпрограмма работал!

чтобы обойти это, Perl считает 0 but true чтобы быть рядом. Если мой добавить подпрограмма не возвращает просто 0, а 0, но правда, мое третье заявление будет работать.

но 0, но правда числовой ноль? Попробуйте вот это:

my $value = "0 but true";
print qq(Add 1,000,000 to it: ) . (1_000_000 + $value) . "\n";
print "Multiply it by 1,000,000: " . 1_000_000 * $value . "\n";

Да, это ноль!

The индекс подпрограмма является очень старой частью Perl и существовала до концепции 0, но правда было вокруг. Предполагается вернуть позицию подстроки, расположенной в строке:

index("barfoo", "foo");   #This returns 3
index("barfoo", "bar");   #This returns 0
index("barfoo", "fu");    #This returns ...uh...

последние заявление возвращает -1. Что означает, если я сделал это:

if ($position = index($string, $substring)) {
   print "It worked!\n";
}
else {
   print "If failed!\n";
}

как я обычно делаю со стандартными функциями, он не будет работать. Если я использовал "barfoo " и" bar", как я сделал во втором заявлении, то else предложение будет выполняться, но если я использовал "barfoo" и "fu", как в третьем, то if пункт "Выполнить". Не то, что я хочу.

однако, если index подпрограмма возвращается 0, но правда для второго утверждения и undef третий заявление, мой if/else предложение сработало бы.

вы также можете увидеть строку " 0E0 " используется в коде Perl, и это означает то же самое, где 0E0 просто означает 0, записанное в экспоненциальной нотации. Однако, поскольку Perl рассматривает только" 0", " или undef как false, он оценивает значение true в логическом контексте.

он жестко закодирован в исходном коде Perl, в частности в Perl_grok_number_flags в числовом формате.c.

читая этот код, я обнаружил, что строка "infinity" (без учета регистра) также проходит тест looks_like_number. Я этого не знал.

в целочисленном контексте он вычисляется как 0 (числовая часть в начале строки) и равен нулю. В скалярном контексте это непустое значение, поэтому оно истинно.

  • if (int("0 but true")) { print "zero"; }

    (нет вывода)

  • if ("0 but true") { print "true"; }

    (печатает true)

0 означает false в Perl (и других языках, связанных с C). По большей части, это разумное поведение. Другие языки (Lua например) лечить 0 как верно и предоставить другой маркер (часто Нил или false) для представления неверного значения.

один случай, когда Способ Perl не работает так хорошо, когда вы хотите вернуть либо число, либо, если функция по какой-то причине не работает, ложное значение. Например, если вы пишете функцию, которая читает строку из файла и возвращает количество символов в строке. Общее использование функции может быть что-то вроде:

while($c = characters_in_line($file)){
    ...
};

обратите внимание, что если количество символов в определенной строке равно 0, то пока цикл закончится до конца файла. Так что characters_in_line функция должна иметь специальный регистр 0 символов и возвращать '0 но правда'. Таким образом, функция будет работать, как предназначен в пока цикл, но также возвращает правильный ответ, если он будет использоваться в качестве числа.

обратите внимание, что это не встроенная часть языка. Скорее, он использует способность Perl интерпретировать строку как число. Поэтому иногда вместо этого используются другие жала. DBI использует "0E0", например. При вычислении в числовом контексте они возвращают 0, но и в логическом контексте, false.

вещи, которые являются ложными:

  • "".
  • "0".
  • вещи, которые привязываются к этим.

"0 but true" не является одним из них, так что это не ложь.

кроме того, Perl возвращает "0 but true" где ожидается число, чтобы сигнализировать, что функция выполнена успешно, даже если она вернула ноль. sysseek пример такой функции. Поскольку ожидается, что значение будет использоваться как число, Perl является закодировано, чтобы считать его числом. В результате никакие предупреждения не выдаются, когда он используется как число, и looks_like_number("0 but true") возвращает true.

другие "истинные нули" можно найти в http://www.perlmonks.org/?node_id=464548.

еще один пример "0 но true":

модуль DBI использует "0E0" в качестве возвращаемого значения для запросов на обновление или удаление, которые не влияют ни на какие записи. Он вычисляет значение true в логическом контексте (указывая, что запрос был выполнен правильно) и 0 в числовом контексте, указывающем, что никакие записи не были изменены запросом.

Я только что нашел доказательство того, что строка "0 but true" активно встроена в интерпретатор, как некоторые люди здесь уже ответили:

$ strings /usr/lib/perl5/5.10.0/linux/CORE/libperl.so | grep -i true
Perl_sv_true
%-p did not return a true value
0 but true
0 but true

" 0 but true "- это строка, как и любая другая, но из-за синтаксиса perl она может служить полезной цели, а именно возвращать целое число ноль из функции без результата"false" (в глазах perl).

и строка не должна быть "0, но true". "0 but false" по-прежнему является"истинным" в булевом смысле.

считаем:

if(x)

for x:        yields:
1             -> true
0             -> false
-1            -> true
"true"        -> true
"false"       -> true
"0 but true"  -> true
int("0 but true") ->false

в результате всего этого вы можете иметь:

sub find_x()

и этот код может печатать "0" в качестве своего вывод:

if($x = find_x)
{
   print int($x) . "\n";
}

Если вы хотите написать функцию, которая возвращает целочисленное значение, или false или undef (т. е. в случае ошибки), то вы должны следить за нулевое значение. Возврат его является ложным и не должен указывать на условие ошибки, поэтому возврат "0, но true" делает возвращаемое значение функции истинным, все еще возвращая нулевое значение, когда математика выполняется на нем.

строка "0 но true" по-прежнему является частным случаем:

for arg in "'0 but true'" "1.0*('0 but true')" \
           "1.0*('0 but false')" 0 1 "''" "0.0" \
           "'false'" "'Ja'" "'Nein'" "'Oui'" \
           "'Non'" "'Yes'" "'No'" ;do
    printf "%-32s: %s\n" "$arg" "$(
        perl -we '
            my $ans=eval $ARGV[0];
            $ans=~s/^(Non?|Nein)$//;
            if ($ans) {
                printf "true:  |%s|\n",$ans
            } else {
                printf "false: |%s|", $ans
          };' "$arg"
        )"
    done

дайте следующее: (обратите внимание на "предупреждение"!)

'0 but true'                    : true:  |0 but true|
1.0*('0 but true')              : false: |0|
Argument "0 but false" isn't numeric in multiplication (*) at (eval 1) line 1.
1.0*('0 but false')             : false: |0|
0                               : false: |0|
1                               : true:  |1|
''                              : false: ||
0.0                             : false: |0|
'false'                         : true:  |false|
'Ja'                            : true:  |Ja|
'Nein'                          : false: ||
'Oui'                           : true:  |Oui|
'Non'                           : false: ||
'Yes'                           : true:  |Yes|
'No'                            : false: ||

... и не забудьте про RTFM!

man -P'less +"/0 but [a-z]*"' perlfunc

       ... "fcntl".  Like "ioctl", it maps a 0 return from the system call
           into "0 but true" in Perl.  This string is true in boolean
           context and 0 in numeric context.  It is also exempt from the
           normal -w warnings on improper numeric conversions. ...

Comments

    Ничего не найдено.