对偶变量的真实性是否总是其字符串部分的真实性?

时间:2019-01-02 18:25:02

标签: perl language-lawyer boolean-expression truthiness

我的Perl 5.26.2 x64(Cygwin)的经验行为是,当且仅当它的 string 部分为true时,doublevar才为true:

# 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'

this起,自2009年以来就是这种情况。

问题:这种行为是否得到保证?

  • Boolean::String说,这就是行为。但是,就向后兼容性而言,我不知道这是否值得依靠。 我也没有在perlsynScalar::Utilperldata#Context中看到明确的陈述。

  • 我在perldata#Scalar-values中看到了以下内容:

      

    如果未定义,则标量值在布尔意义上被解释为FALSE,如果为空字符串或数字0(或其等效字符串“ 0”),则为TRUE,否则为TRUE。布尔上下文只是一种特殊的标量上下文,在这种情况下,从未执行过对字符串或数字的转换。

    不幸的是,“从未执行过转换……”的说法并没有告诉我解释器正在查看对偶变量的哪一部分!

  • 类似地,Chas。欧文斯的related answer

      

    真实性测试首先查看字符串

    但是,如果它查看字符串 first ,那么它查看 second 的时间是什么?

编辑我的理解是,如果overload定义在变量是否为doublevar上,则bool重载将得到控制。我想知道未超载的情况。

编辑2 池上的答案here指出,PL_sv_yesPL_sv_no 也有NV({ {1}})组件。对于奖励积分:),如果对偶变量具有一个,则NV对真实性有影响吗? (让我知道该答案是否确实涉及到足以应得的一个单独问题。)

2 个答案:

答案 0 :(得分:6)

是的,至少到目前为止。 SvTRUE_common宏通常用于确定布尔上下文中SV在何处为“ true”。这是在perl 5.26.1源中的sv.h中定义的方式:

#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总是通过此检查,因此对doublevar的布尔测试是其字符串表示形式是否为真(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开发人员会警惕更改这种长期存在的逻辑。

答案 1 :(得分:2)

这归结为如何在布尔上下文中以字符串或数字形式测试标量?

在Perl中,文档是最接近标准的文档。因此,如果文档中没有声明,则正式答案必须为:不,没有保证

自从文档关闭了几次之后,谈论了上下文和转换,但具体来说不要阐明要完成的测试,我会说确实必须将其视为实施细节。您不能“依赖”它。

如果需要严格的可靠性,则一个解决方案是一个简单的类,可以确保测试您所需要的。

更实际地说,似乎是在if ($v)中测试了字符串部分,如果没有,则进行数字测试(没有像文档所说的那样进行实际转换)。由于您询问的是已设置为dualvar的变量,因此对于这些变量,将始终只是字符串测试。