比较Perl中的两个未定义值。

huangapple go评论60阅读模式
英文:

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 returns undef.

它似乎是比较 undef ne undef 返回 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.

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. Converting undef 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 special false 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 or false from a value is to negate it twice.

从一个值获取 truefalse 的最简单方法是对其进行两次否定。

my $normalized = !!$x;

The simplest way to get 1 if true or 0 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 &#39;say defined(undef ne undef) ? q(Defined) : q(Undefined)&#39;
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 ? &quot;Defined! &lt;$result&gt;&quot; : &quot;Not defined&quot;

The output shows that an undef value is different than a PL_no value (see @ikegami's answer):

Defined! &lt;&gt;
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 &quot;&quot; [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.

huangapple
  • 本文由 发表于 2023年2月23日 22:02:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545843.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定