英文:
Comparing two undefs in Perl
问题
undef ne undef
返回 undef
。Perl 有将其转换为 "boolean" 的成语方式吗?
此外,我发现以下情况有点奇怪:
undef ne undef || 0; # 0
(undef ne undef) || 0; # undef
能否请您解释一下发生了什么?
英文:
It seems comparison undef ne undef
returns undef. Does Perl have idiomatic way to convert it to perls "boolean"?
Also I find following to be strange:
undef ne undef || 0; # 0
(undef ne undef) || 0; # undef
Could you explain, please, what is happening?
答案1
得分: 6
It seems comparison
undef ne undef
returnsundef
.
它似乎是比较 undef ne undef
返回 undef
。
It doesn't.
实际上不是这样的。
ne
returns either the special scalartrue
(known as&PL_yes
internally) or the special scalarfalse
(&PL_no
), neverundef
. In this particular case, it returnsfalse
.
ne
返回特殊标量 true
(在内部称为 &PL_yes
)或特殊标量 false
(&PL_no
),从不返回 undef
。在这个特定情况下,它返回 false
。
(The results are the same in earlier versions of Perl, but
is_bool
was only introduced in Perl v5.36.)
(在较早版本的Perl中,结果是相同的,但is_bool
仅在Perl v5.36中引入。)
false
is a scalar that contains the integer zero, the float zero and the empty string.
false
是一个标量,它包含整数零、浮点零和空字符串。
I find following to be strange:
我发现以下内容有点奇怪:
That's because it's not true. The two snippets are 100% equivalent, and they both return
0
.
这是因为它不是真的。这两个代码片段完全等效,它们都返回 0
。
ne
is a string comparison operator. So it starts by casting its operands into strings. Convertingundef
to a string produces the empty string, and emits a warning. Since the empty string is equal to the empty string,ne
returns a false value, and specifically the specialfalse
scalar.
ne
是一个字符串比较运算符。因此,它首先将其操作数转换为字符串。将 undef
转换为字符串会产生空字符串,并发出警告。由于空字符串等于空字符串,ne
返回一个假值,具体来说是特殊的 false
标量。
Since
false
is a false value,||
evaluates and returns its right-hand side value (0
).
由于 false
是一个假值,||
会评估并返回其右侧的值(0
)。
Does Perl have an idiomatic way to convert it to Perl's "boolean"?
Perl 是否有将其转换为 Perl 中的 "boolean" 的惯用方法?
The simplest way to get
true
orfalse
from a value is to negate it twice.
从一个值获取 true
或 false
的最简单方法是对其进行两次否定。
my $normalized = !!$x;
The simplest way to get
1
if true or0
if false is to use the conditional operator.
如果为真,则获取 1
,如果为假,则获取 0
的最简单方法是使用条件运算符。
my $normalized = $x ? 1 : 0;
英文:
> It seems comparison undef ne undef
returns undef
.
It doesn't.
ne
returns either the special scalar true
(known as &PL_yes
internally) or the special scalar false
(&PL_no
), never undef
. In this particular case, it returns false
.
$ perl -e'
use v5.36;
use experimental qw( builtin );
use builtin qw( is_bool );
sub inspect {
!defined( $_[0] ) ? "[undef]" :
is_bool( $_[0] ) ? ( $_[0] ? "[true]" : "[false]" ) :
$_[0]
}
my $x = undef ne undef; # Line 12
say inspect( $x ); # [false]
'
Use of uninitialized value in string ne at -e line 12.
Use of uninitialized value in string ne at -e line 12.
[false]
(The results are the same in earlier versions of Perl, but is_bool
was only introduced in Perl v5.36.)
false
is a scalar that contains the integer zero, the float zero and the empty string.
$ perl -e'
use v5.36;
use experimental qw( builtin );
use builtin qw( false );
{ my $x = ""; say 0+$x; say "[$x]"; } # Line 6
say "--";
{ my $x = 0; say 0+$x; say "[$x]"; }
say "--";
{ my $x = false; say 0+$x; say "[$x]"; }
'
Argument "" isn't numeric in addition (+) at -e line 6.
0
[]
--
0
[0]
--
0
[]
> I find following to be strange:
That's because it's not true. The two snippets are 100% equivalent, and they both return 0
.
$ perl -e'
use v5.36;
use experimental qw( builtin );
use builtin qw( is_bool );
sub inspect {
!defined( $_[0] ) ? "[undef]" :
is_bool( $_[0] ) ? ( $_[0] ? "[true]" : "[false]" ) :
$_[0]
}
{ my $x = undef ne undef || 0; say inspect( $x ); } # Line 12 # 0
{ my $x = ( undef ne undef ) || 0; say inspect( $x ); } # Line 13 # 0
'
Use of uninitialized value in string ne at -e line 12.
Use of uninitialized value in string ne at -e line 12.
0
Use of uninitialized value in string ne at -e line 13.
Use of uninitialized value in string ne at -e line 13.
0
(The results are the same in earlier versions of Perl, but is_bool
was only introduced in Perl v5.36.)
> Could you explain, please, what is happening?
ne
is a string comparison operator. So it starts by casting its operands into strings. Converting undef
to a string produces the empty string, and emits a warnings. Since the empty string is equal to the empty string, ne
returns a false value, and specifically the special false
scalar.
Since false
is a false value, ||
evalutes and returns its right-hand side value (0
).
> Does Perl have idiomatic way to convert it to perls "boolean"?
The simplest way to get true
or false
from a value is to negate it twice.
my $normalized = !!$x;
The simplest way to get 1
if true or 0
if false is to use the conditional operator.
my $normalized = $x ? 1 : 0;
答案2
得分: 1
undef ne undef
不会返回另一个 undef
。我认为你可能有其他情况:
perl -lE 'say defined(undef ne undef) ? q(Defined) : q(Undefined)'
Defined
以下是一个更复杂的程序,展示了Perl在底层查看的内容:
use Devel::Peek qw(Dump);
use v5.10;
my $null;
Dump($null);
my $result = undef ne undef // 17;
Dump($result);
say defined $result ? "Defined! <$result>" : "Not defined";
输出显示一个 undef
值与 PL_no
值不同(参见 @ikegami 的回答):
Defined! <0>
SV = NULL(0x0) at 0x7f980f8163a0
REFCNT = 1
FLAGS = ()
SV = PVNV(0x7f980e8098b0) at 0x7f980f82d590
REFCNT = 1
FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x101e9cac5 "" [BOOL PL_No]
CUR = 0
LEN = 0
还要注意,$result
中的值并不是 17
,就像如果定义-或运算符 //
的左操作数是 undef
一样。它只是假的。
英文:
First, undef ne undef
does not return another undef
. I think you probably had something else going on:
$ perl -lE 'say defined(undef ne undef) ? q(Defined) : q(Undefined)'
Defined
Here's a more involved program that shows what Perl is looking at underneath the hood:
use Devel::Peek qw(Dump);
use v5.10;
my $null;
Dump($null);
my $result = undef ne undef // 17;
Dump($result);
say defined $result ? "Defined! <$result>" : "Not defined"
The output shows that an undef value is different than a PL_no value (see @ikegami's answer):
Defined! <>
SV = NULL(0x0) at 0x7f980f8163a0
REFCNT = 1
FLAGS = ()
SV = PVNV(0x7f980e8098b0) at 0x7f980f82d590
REFCNT = 1
FLAGS = (IOK,NOK,POK,IsCOW,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x101e9cac5 "" [BOOL PL_No]
CUR = 0
LEN = 0
Also note that the value in $result
is not 17
as it would be if the left hand side of the defined-or //
were undef. It's merely false.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论