Различные логические операторы не возвращают пустую строку, они возвращают ложное или истинное значение во всех трех простых скалярных типах. Просто похоже, что он возвращает пустую строку, потому что 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 как факт, у меня было бы меньше работы.
Ответы на вопросы в разделе РЕДАКТИРОВАТЬ:
Каким образом использование строки, которая является истинной (например, "ложной") в качестве строкового представления ложных значений, изменит смысл существующего кода?
Единственные особенности 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» (оба из которых ложны), это приведет к поломке некоторого допустимого кода.
Я предполагаю, что контекст строки настолько распространен в Perl, что единственный вариант, ведущий к разумной семантике, - это если логическое значение сохранит свое значение после циклического перехода к строке и от нее ...
да.
person
Chas. Owens
schedule
12.10.2010