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。
问题:这是保证的行为吗?
Boolean::String
说这就是行为。但是,就向后兼容性而言,我不知道这是否是我可以依赖的。
我也没有在 perlsyn, Scalar::Util
, or perldata#Context
.
中看到明确的声明
我确实在 perldata#Scalar-values
中看到以下内容:
A scalar value is interpreted as FALSE in the Boolean sense if it is undefined, the null string or the number 0 (or its string equivalent, "0"), and TRUE if it is anything else. The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed.
不幸的是,"no conversion ... is ever performed" 的声明没有告诉我解释器正在查看 dualvar 的哪一部分!
同样,Chas。欧文斯的 related answer 说
the truthiness test looks at strings first
但是如果它查看字符串 first,它会查看什么 second,什么时候查看?
Edit 我的理解是,如果 overload
定义在变量上,无论是否为 dualvar,bool
重载将控制。我想知道非重载情况。
编辑2池上的回答here指出PL_sv_yes
和PL_sv_no
也有NV
(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 开发人员会对改变这种长期存在的逻辑持谨慎态度。
我的 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。
问题:这是保证的行为吗?
Boolean::String
说这就是行为。但是,就向后兼容性而言,我不知道这是否是我可以依赖的。 我也没有在 perlsyn,Scalar::Util
, orperldata#Context
. 中看到明确的声明
我确实在
perldata#Scalar-values
中看到以下内容:A scalar value is interpreted as FALSE in the Boolean sense if it is undefined, the null string or the number 0 (or its string equivalent, "0"), and TRUE if it is anything else. The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed.
不幸的是,"no conversion ... is ever performed" 的声明没有告诉我解释器正在查看 dualvar 的哪一部分!
同样,Chas。欧文斯的 related answer 说
the truthiness test looks at strings first
但是如果它查看字符串 first,它会查看什么 second,什么时候查看?
Edit 我的理解是,如果 overload
定义在变量上,无论是否为 dualvar,bool
重载将控制。我想知道非重载情况。
编辑2池上的回答here指出PL_sv_yes
和PL_sv_no
也有NV
(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 开发人员会对改变这种长期存在的逻辑持谨慎态度。