Всегда ли истинность дуалава такова, как его струнной части? - PullRequest
0 голосов
/ 02 января 2019

Эмпирическое поведение моего Perl 5.26.2 x64 (Cygwin) таково, что дуалвар правдив тогда и только тогда, когда его строка часть правдива:

# Falsy number, truthy string => truthy
$ perl -MScalar::Util=dualvar -E 'my $v=dualvar 0, "foo"; say "yes" if $v'
yes

# Truthy number, falsy string => falsy
$ perl -MScalar::Util=dualvar -E 'my $v=dualvar 1, ""; say "yes" if $v'

# Truthy number, truthy string => truthy
$ perl -MScalar::Util=dualvar -E 'my $v=dualvar 1, "foo"; say "yes" if $v'
yes

# Falsy number, falsy string => falsy
$ perl -MScalar::Util=dualvar -E 'my $v=dualvar 0, ""; say "yes" if $v'

Это былослучай с 2009 года за это .

Вопрос: Это гарантированное поведение?

  • Boolean::String говорит, что это поведение.Тем не менее, я не знаю, могу ли я на это положиться с точки зрения обратной совместимости.Я также не вижу выражений в perlsyn , Scalar::Util или perldata#Context.

  • Я вижу следующее в perldata#Scalar-values:

    Скалярное значение интерпретируется как FALSE в логическом смысле, если оно не определено, нулевая строка или число 0 (илиего строковый эквивалент, "0") и TRUE, если это что-то еще.Логический контекст - это просто особый вид скалярного контекста, в котором преобразование в строку или число никогда не выполняется.

    Утверждение, что «преобразование не выполняется, к сожалению, никогда не выполняется»скажите мне, на какую часть дуалвара смотрит переводчик!

  • Аналогично, час. связанный ответ Оуэнса говорит, что

    тест на правдивость сначала смотрит на строки

    Но если он смотрит на строки сначала ,что это смотрит на секунду и когда?

Редактировать Я понимаю, что если overloadопределенная для переменной, dualvar или нет, перегрузка bool будет управлять.Меня интересует случай незагруженности.

Редактировать 2 Ответ Икегами здесь указывает на то, что PL_sv_yes и PL_sv_no также иметь компонент NV (double).Для бонусных очков :), влияет ли NV на правдивость, если она есть у дуалвара?(Дайте мне знать, достаточно ли этот ответ достаточно, чтобы заслуживать отдельного вопроса.)

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Да, по крайней мере, пока.Макрос SvTRUE_common обычно используется для определения, где SV является «истинным» в логическом контексте.Вот как это определено в sv.h в источнике perl 5.26.1:

#define SvTRUE_common(sv,fallback) (            \
      !SvOK(sv)                     \
    ? 0                     \
    : SvPOK(sv)                     \
    ? SvPVXtrue(sv)                 \
    : (SvFLAGS(sv) & (SVf_IOK|SVf_NOK))         \
    ? (   (SvIOK(sv) && SvIVX(sv) != 0)     \
       || (SvNOK(sv) && SvNVX(sv) != 0.0))      \
    : (fallback))

После того, как скаляр пройдет тест SvOK (определен ли он), следующая проверка будет SvPOK -- имеет ли скаляр допустимое внутреннее строковое представление.Dualvars всегда проходит эту проверку, поэтому логический тест дуалар заключается в том, является ли его строковое представление истинным (SvPVXtrue(...)).

Код в Perl отличается от 5.6.2

I32
Perl_sv_true(pTHX_ register SV *sv)
{
    if (!sv)
        return 0;
    if (SvPOK(sv)) {
        register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
                (tXpv->xpv_cur > 1 ||
                (tXpv->xpv_cur && *tXpv->xpv_pv != '0')))
            return 1;
        else
            return 0;
    }
    else {
        ...

но логика та же - сначала проверьте SvPOK, а затем верните, не является ли строковое представление не пустым и не равным "0".

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

0 голосов
/ 02 января 2019

Это сводится к тому, как скаляр проверяется в логическом контексте, в виде строки или числа?

В Perl документация ближе всего к стандарту. Таким образом, если в документах нет утверждений, то формальный ответ должен быть: Нет, это не « гарантированное поведение ».

Поскольку документы несколько раз дразнящим образом закрываются, говоря об этом контексте и конверсиях, и все же конкретно не не разъясняет, какой тест выполнен, я бы сказал, что это действительно должно быть воспринято как реализация подробно. Вы не можете " полагаться " на это.

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

В более практическом смысле представляется, что в if ($v) проверяется только строковая часть, а если ее там нет, то проводится числовой тест (без фактического преобразования, как говорят документы). Когда вы спросите о переменных, которые были установлены как dualvar, то для них это будет строковый тест.

...