dualvar 的真实性总是它的字符串部分的真实性吗?

Is the truthiness of a dualvar always that of its string part?

我的 Perl 5.26.2 x64 (Cygwin) 的经验行为是 dualvar 是真实的当且仅当它的 string 部分是真实的:

# 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 年以来一直如此this

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

Edit 我的理解是,如果 overload 定义在变量上,无论是否为 dualvar,bool 重载将控制。我想知道非重载情况。

编辑2池上的回答here指出PL_sv_yesPL_sv_noNV (double) 组件。对于奖励积分:),如果 dualvar 有 NV,NV 对真实性有任何影响吗? (让我知道这个答案是否真的涉及到足以值得一个单独的问题。)

Question: Is this guaranteed behaviour?

这归结为如何在布尔上下文中测试标量,作为字符串还是数字?

在 Perl 中,文档是最接近标准的东西。因此,如果文档中没有声明,那么正式答案必须是:不,它不是“保证行为”。

由于文档有几次非常接近,谈论的是上下文和转换,但具体来说不要说明完成了哪个测试我想说这必须确实被视为实施细节。你不能“依赖”。

如果需要严格的可靠性,一种解决方案是简单的class,确保测试您需要的内容。

更实际地说,似乎在 if ($v) 中测试的是字符串部分,如果不存在,则进行数字测试(没有文档所说的实际转换)。当您询问已设置为 dualvar 的变量时,对于那些将是字符串测试的变量。

是的,至少到目前为止。 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 总是通过这个检查,所以 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再检查return字符串表示是否不为空且不等于"0".

我认为未来几代 Perl 开发人员会对改变这种长期存在的逻辑持谨慎态度。