Различные логические операторы не возвращают пустую строку, они возвращают значение false или true во всех трех простых скалярных типах. Похоже, он возвращает пустую строку, потому что print
вызывает строковый контекст в своих аргументах:
#!/usr/bin/perl
use strict;
use warnings;
use Devel::Peek;
my $t = 5 > 4;
my $f = 5 < 4;
Dump $t;
Dump $f;
Выход:
SV = PVNV(0x100802c20) at 0x100827348
REFCNT = 1
FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
IV = 1
NV = 1
PV = 0x100201e60 "1"\0
CUR = 1
LEN = 16
SV = PVNV(0x100802c40) at 0x100827360
REFCNT = 1
FLAGS = (PADMY,IOK,NOK,POK,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x100208ca0 ""\0
CUR = 0
LEN = 16
Для тех, кто не знаком с внутренними компонентами Perl 5, PVNV
- это скалярная структура, которая содержит все три простых скалярных типа (целое число IV
, число с плавающей запятой двойной точности NV
и строка PV
). Флаги IOK
, NOK
и POK
означают, что целочисленные, двойные и строковые значения синхронизированы (для некоторого определения в синхронизации), поэтому может использоваться любое из них (т. Е. Преобразование не требуется. иметь место, если вы используете его как целое число, двойное число или строку).
Я предполагаю, что пустая строка была выбрана для ложной строки, потому что она меньше и больше соответствует идее ложной строки, чем "0"
. Не обращайте внимания на мое утверждение о том, что оно меньше, ""
и "1"
имеют одинаковый размер: шестнадцать символов. Так сказано прямо на свалке. Perl 5 добавляет дополнительное пространство к строкам, чтобы они могли быстро расти.
Ох, и я тебя ненавижу. Исследуя это, я обнаружил, что я лгал в perlopquick
и теперь должен найти способ исправить это. Если бы вы были такими же, как все остальные овцы, и просто приняли странность поверхности Perl 5 как факт, у меня было бы меньше работы.
Ответы на вопросы в разделе РЕДАКТИРОВАНИЯ:
Как использование строки true (например, false) в качестве строкового представления ложных значений изменит смысл существующего кода?
Единственное, что особенного в PL_sv_yes и PL_sv_no (канонически истинных и ложных значениях, возвращаемых операторами сравнения), заключается в том, что они доступны только для чтения и создаются perl
, а не программой, которая выполняется. Если вы измените их, это не изменит тест на достоверность, поэтому PL_sv_no, установленное на "false"
, будет считаться истиной. Вы даже можете сделать это самостоятельно (этот код перестает работать в какой-то момент между Perl 5.18 и последней версией Perl), используя недокументированные функции perl
:
#!/usr/bin/perl
use strict;
use warnings;
use Scalar::Util qw/dualvar/;
BEGIN {
# use the undocumented SvREADONLY function from Internals to
# modify a reference to PL_sv_no's readonly flag
# note the use of & to make the compiler not use SvREADONLY's
# prototype, yet another reason prototypes are bad and shouldn't
# be used
&Internals::SvREADONLY(\!!0, 0);
# set PL_sv_no to a dualvar containing 0 and "false"
${\!!0} = dualvar 0, "false";
}
if (5 < 4) {
print "oops\n";
}
выходы
opps
Это потому, что тест на правдивость сначала проверяет строки.
Можно ли сказать, что код, который меняет семантику после такого изменения, менее надежен / корректен, чем мог бы быть?
Это будет прямо сломано. Даже если вы ограничитесь установкой значения int 0 или строки «0» (оба значения false), это приведет к нарушению допустимого кода.
Я полагаю, что строковый контекст настолько распространен в Perl, что единственная опция, ведущая к разумной семантике, - это если логическое значение сохраняет свое значение после округления до строки и из строки ...
Да.