perl 如何检查LVALUE是否表示SCALAR

mzsu5hc0  于 2023-02-05  发布在  Perl
关注(0)|答案(2)|浏览(143)

多年来,我一直使用包含以下条件的代码

ref \$_[0] eq 'SCALAR'

我总是希望有一个ARRAYSCALAR,但最近我把substr()传入那个参数。意外的事情发生了。条件返回了一个false值。
然后我想通了,ref返回的是LVALUE而不是SCALAR
因为LVALUE是一种奇怪的引用类型,所以我需要检查它后面是否有标量。
如何检查LVALUE是否代表SCALAR

mefy6pfw

mefy6pfw1#

一个LVALUE是一个特殊的魔法值,当它被赋值时会执行操作。例如,调用f($hash{foo})并不会立即在%hash中创建foo条目;而是创建一个临时的LVALUE并将其作为$_[0]传递给sub。如果随后将$_[0]赋值给,则该值将存储为$hash{foo}
一个LVALUE是一个标量(也就是说,它只保存一个值),只是一个奇数类型的标量。
因此,代码很可能可以通过接受SCALAR和LVALUE作为有效值来修复。但这将取决于执行检查的确切原因。也可能是这样的检查是一个逻辑错误,实际上并不需要,或者有bug。例如,ref \$_[0]不应该返回ARRAY。

jxct1oxe

jxct1oxe2#

Perl 5.36中reftype( $x )(从Scalar::Util)可以返回的值:
| 价值|说明|是否可以取消引用?|
| - ------|- ------|- ------|
| undef|$x的值不是引用。|没有|
| "ARRAY"|$x引用一个数组(PVAV类型标量。|作为数组|
| "HASH"|$x引用散列(PVHV类型标量)。|就像一堆垃圾|
| "CODE"|$x引用子对象(PVCV类型的标量)。|作为代课老师|
| "GLOB"|$x引用一个glob(PVGV类型的标量)。|作为glob、标量、数组、散列或代码|
| x1米11米1x|$x引用PVLV类型的标量,但有一些例外。|作为标量|
| "REGEXP"|$x引用了一个标量,该标量是编译后的regexp模式(REGEXP类型的标量)。|作为标量|
| "IO"|$x引用了一个IO对象标量(PVIO类型的标量)。|没有|
| "FORMAT"|$x引用PVFM类型的标量。我不知道是否有可能得到一个格式的引用。|没有|
| "INVLIST"|$x引用INVLIST类型的标量。这是一个内部类型。您不应该看到它。|没有|
| "REF"|$x引用包含引用的标量。|作为标量|
| "VSTRING"|$x引用包含版本字符串的标量。|作为标量|
| "SCALAR"|$x引用了其他内容。|作为标量|
例外情况:

  • 返回SCALAR以引用绑定的PVLV。
  • 返回REF以引用包含引用的PVLV。

警告:

  • 当前包含引用的魔法变量返回REF,不包含引用的魔法变量返回SCALAR,但是魔法变量的值在每次获取时都会改变。

ref( $x )类似,它返回false(特殊标量,而不是字符串false),而不是undef。如果$x的值不是引用。如果$x是对某个祝福对象的引用,则返回该对象被祝福的包。否则,它返回与reftype( $x )相同的结果。我认为refreftypeblessed的混合。
我总是期望有ARRAYSCALAR
reftype( \$_[0] )永远不会是ARRAY
ref( \$_[0] )可以返回ARRAY,但只有当您执行类似my $x; bless( \$x, "ARRAY" ); f( $x )的奇怪操作时才可以(这就是我认为它已损坏的原因)。
$_[0]总是指向标量。数组元素只能是标量。参数只能是标量。
如何检查LVALUE是否代表SCALAR
它总是一个标量。
在本例中,不需要reftyperef来告诉你这一点,数组元素的值总是标量,所以$_[0]总是标量。
如上所述,PVLV类型的标量会返回它。它是一种魔法标量。大多数魔法标量都是PVMG类型,但有些魔法类型会利用PVLV标量提供的额外字段。PVLV标量由$h{EXPR}作为参数返回,pos作为左值返回,substr作为左值返回,vec作为左值返回,等等。

相关问题