Perl 二元论的真实性总是它的弦部分的真实性吗?

Perl 二元论的真实性总是它的弦部分的真实性吗?,perl,language-lawyer,boolean-expression,truthiness,Perl,Language Lawyer,Boolean Expression,Truthiness,我的Perl 5.26.2 x64(Cygwin)的经验行为是,dualvar是truthy当且仅当其字符串部分是truthy时: # 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::Ut

我的Perl 5.26.2 x64(Cygwin)的经验行为是,dualvar是truthy当且仅当其字符串部分是truthy时:

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

问题:这种行为有保证吗

  • 说这就是行为。然而,就向后兼容性而言,我不知道这是否是我可以依赖的。 我也没有在或中看到明确的声明

  • 我确实看到以下情况:

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

    不幸的是,“从未执行任何转换”的语句并没有告诉我解释器正在查看dualvar的哪个部分

  • 同样,查斯。欧文斯说

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

    但如果它首先看字符串,那么它第二次看什么,什么时候看

编辑我的理解是,如果在变量上定义了,无论是否定义了dualvar,
bool
重载将控制。我想知道没有超载的情况


Edit 2ikegami的回答指出
PL_sv_yes
PL_sv_no
也有一个
NV
double
)组件。对于加分:),如果dualvar有真实性,NV对真实性有影响吗?(让我知道这个答案是否涉及足够多的问题。)

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

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

由于文档有几次非常接近,讨论了上下文和转换,但没有明确说明要进行哪项测试,所以我认为这确实是一个实现细节。你不能“依赖”它

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


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

是的,至少到目前为止是这样。
SvTRUE\u 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
——标量是否具有有效的内部字符串表示形式。dualvar始终通过此检查,因此dualvar的布尔测试是其字符串表示是否为真(
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开发人员会对改变这种长期存在的逻辑持谨慎态度。

这是我记得看到的研究得最好的问题。@zdim感谢您的回答和赞扬!我认为原因是像
abc
(这是真的)这样的字符串将numif设置为0(这是假的)。因此,如果一个标量包含一个字符串及其numification,那么检查该字符串可以确保正确的结果mob,感谢您提供的详细信息!还感谢mob-rule.com,它非常酷!