双变量的真实性总是它的字符串部分吗?

cxw*_*cxw 9 perl boolean-expression language-lawyer truthiness

我的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'
Run Code Online (Sandbox Code Playgroud)

自2009年以来一直如此.

问题:这是保证的行为吗?

  • Boolean::String说这是行为.但是,就向后兼容性而言,我不知道这是否可以依赖.我还没有看到在明确声明perlsyn,Scalar::Utilperldata#Context.

  • 我确实看到以下内容perldata#Scalar-values:

    如果未定义标量值,则在布尔义上将标量值解释为FALSE,空字符串或数字0(或其等效字符串,"0"),如果是其他任何值,则为TRUE.布尔上下文只是一种特殊的标量上下文,不会执行到字符串或数字的转换.

    不幸的是,"没有进行转换......"的说法并没有告诉我解释器正在考虑的双变量的哪个部分!

  • 同样,Chas.欧文斯的相关答案说明了这一点

    真实性测试首先考虑字符串

    但是,如果它首先查看字符串,它看起来第二,什么时候?

编辑我的理解是,如果overload在变量doublevar上定义,则bool过载将控制.我想知道非重载的情况.

编辑2 ikegami的答案在这里指出,PL_sv_yes并且PL_sv_no 还有一个NV(double)组件.对于奖励积分:),如果双变量有一个,NV对真实性有任何影响吗?(请告诉我,如果答案实际上足够值得一个单独的问题.)

mob*_*mob 6

是的,至少到目前为止.该SvTRUE_common宏通常用来决定在哪里的SV是在布尔环境"真".以下是sv.hperl 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))
Run Code Online (Sandbox Code Playgroud)

标量通过SvOK测试后(无论是否已定义),下SvPOK一项检查是- 标量是否具有有效的内部字符串表示.Dualvars总是通过这个检查,因此dualvar的布尔测试是它的字符串表示是否为true(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 {
        ...
Run Code Online (Sandbox Code Playgroud)

但逻辑是相同的 - 先检查SvPOK然后返回字符串表示是否为空且不等于"0".

我认为未来的Perl开发人员会对改变这种长期存在的逻辑保持警惕.

  • 我认为原因是像`abc`(这是真的)这样的字符串数字为0(这是假的).因此,如果标量包含字符串及其数字,则检查字符串可确保正确的结果 (2认同)