Может кто-нибудь объяснить, что именно строка «0, но правда» означает в Perl? Насколько я понимаю, он равен нулю в целочисленном сравнении, но оценивает значение true при использовании в качестве логического. Это верно? Является ли это нормальным поведением языка или это специальная строка, рассматриваемая как специальный случай в интерпретаторе?Что означает «0, но правда» в Perl?
ответ
Это нормальное поведение языка. Цитируя perlsyn
: справочную страницу
Число
0
, строки'0'
и""
, пустой список()
иundef
все ложь в логическом контексте. Все остальные значения верны. Отрицание действительного значения на!
илиnot
возвращает специальное ложное значение. Когда оценивается как строка, он обрабатывается как""
, но в качестве номера рассматривается как0
.
Из-за этого, там должен быть способ вернуть 0
из системного вызова, который рассчитывает вернуть 0
как (успешный) возвращаемого значения и оставить путь сигнала случай сбоя на самом деле возвращение ложным стоимость. "0 but true"
служит этой цели.
Nit: '0, но true' относится не только к системным вызовам. – 2008-09-24 22:06:24
В некоторых модулях используется строка «0E0», которая оценивается как 0 как число, а true как логическое. – 2009-07-20 13:20:25
OMG Perl настолько неоднозначен: O – 2010-11-07 23:22:51
В целочисленном контексте он вычисляет 0 (числовая часть в начале строки) и равен нулю. В скалярном контексте это непустое значение, поэтому оно верно.
if (int("0 but true")) { print "zero"; }
(нет вывода)
if ("0 but true") { print "true"; }
(печатает верно)
Если вы хотите, чтобы написать функцию, которая возвращает либо целое значение , или false или undef (т. для случая ошибки), то вам нужно следить за нулевым значением. Возврат является ложным и не должен указывать на условие ошибки, поэтому возвращение «0, но true» делает функцию возвращаемым значением true, все еще передавая нулевое значение, когда на нем выполняется математика.
Кроме того, что говорил другие, "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, но верно» является строкой, так же, как любой другой, но из-за синтаксисом языка Perl он может служить полезной целью, а именно возвращать целочисленный ноль из функции без результата «false» (в глазах Perl).
И строка не обязательно должна быть «0, но верно». «0, но 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 в Perl (и других языках, связанных с C). По большей части это разумное поведение. Другие языки (например, Lua) обрабатывают как истинные и предоставляют другой токен (часто nil или false), чтобы представить недействительное значение.
Один случай, когда способ Perl не работает так хорошо, - это когда вы хотите вернуть либо число, либо, если функция по какой-то причине не работает, ложное значение. Например, если вы пишете функцию, которая читает строку из файла и возвращает количество символов в строке. Общее использование функции может быть что-то вроде:
while($c = characters_in_line($file)){
...
};
Обратите внимание, что если количество символов на конкретной линии 0, то в то время как цикл завершится до конца файла. Таким образом, функция characters_in_line должна иметь специальный регистр 0 символов и вместо этого возвращать '0, но true'. Таким образом, функция будет работать так, как это предусмотрено в , в то время как цикл, но также возвращает правильный ответ, если он будет использоваться в качестве числа.
Обратите внимание, что это не встроенная часть языка. Скорее, он использует способность Perl интерпретировать строку как число. Поэтому вместо этого иногда используются другие укусы. DBI использует «0E0», например. При оценке в числовом контексте они возвращают , но в булевом контексте false.
Вы также можете увидеть строку "0E0" used in Perl code, а это означает то же самое, где 0E0 просто означает 0, записанное в экспоненциальном обозначении. Однако, поскольку Perl учитывает только «0», «» или «undef» как false, он вычисляет true в булевом контексте.
Другой пример «0, но верно»:
модуль DBI использует «0E0» в качестве возвращаемого значения UPDATE или DELETE запросов, которые не влияют на какие-либо записи. Он оценивает значение true в булевом контексте (указывая, что запрос был выполнен правильно) и 0 в числовом контексте, указывающем, что запрос не изменялся.
Я только что нашел доказательство того, что строка «0, но истина» actially встроенный в интерпретатор, как некоторые люди здесь уже ответили:
$ 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"
.- Вещи, которые подтягивают их.
"0 but true"
не является одним из тех, поэтому он не является ложным.
Кроме того, Perl возвращает "0 but true"
, где ожидается число, чтобы сигнализировать о том, что функция выполнена успешно, даже если она вернула нуль. sysseek - пример такой функции. Поскольку ожидается, что значение будет использоваться как число, Perl кодируется, чтобы считать его числом. В результате никаких предупреждений не выдается, когда они используются как число, а looks_like_number("0 but true")
возвращает true.
Другие «истинные нули» можно найти по адресу http://www.perlmonks.org/?node_id=464548.
Потому что он жестко закодирован в ядре Perl для обработки его как числа. Это взлом, чтобы сделать соглашения Perl и соглашения ioctl
; от perldoc -f ioctl
:
Возвращаемое значение
ioctl
(иfcntl
) выглядит следующим образом:if OS returns: then Perl returns: -1 undefined value 0 string "0 but true" anything else that number
Таким образом, Perl возвращает истину в случае успеха и ложна на провал, но вы все еще может легко определить фактическое значение возвращаемый операционной системы:
$retval = ioctl(...) || -1; printf "System returned %d\n", $retval;
специальная строка
"0 but true"
является освобождаются от-w
жалоб о неправильных числовых преобразованиях.
Он жестко закодирован в исходном коде Perl, в частности, в Perl_grok_number_flags in numeric.c.
Чтение этого кода Я обнаружил, что строка «бесконечность» (без учета регистра) проходит тест look_like_number. Я этого не знал.
Значение 0 but true
является специальным чехлом на Perl. Хотя для ваших простых смертных глаз это не похоже на число, мудрое и всезнающее, что Perl понимает, что это действительно число.
Это связано с тем, что, когда подпрограмма Perl возвращает значение 0, предполагается, что подпрограмма завершилась неудачно или вернула ложное значение.
Представьте меня подпрограмму, которая возвращает сумму двух чисел:
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 but true a numeric zero? Попробуйте следующее:
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";
Yup, it is zero!
Подпрограмма index является очень старой частью 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
работало бы.
Строка `` 0, но это правда '' по-прежнему особый случай:
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. ...
Строка `` 0E0 "` another похожа на `" 0, но true ". Вместо жесткого кодирования это является следствием экспоненциальной нотации Perl. Это непустая ненулевая строка, это правда. В качестве числа это 0. DBI использует его как возвращаемое значение из таких вещей, как `execute`, чтобы указать, что SQL-оператор работал, но никаких строк не было затронуто. – Schwern 2011-03-16 08:58:09
Я понимаю причину особого обращения с «0, но верно» для предупреждений при преобразовании в число, но я все еще думаю, что look_like_number * должен * вернуть false. – bart 2011-03-17 12:17:05