多年来,我一直使用包含以下条件的代码
ref \$_[0] eq 'SCALAR'
我总是希望有一个ARRAY或SCALAR,但最近我把substr()传入那个参数。意外的事情发生了。条件返回了一个false值。然后我想通了,ref返回的是LVALUE而不是SCALAR。因为LVALUE是一种奇怪的引用类型,所以我需要检查它后面是否有标量。如何检查LVALUE是否代表SCALAR?
ARRAY
SCALAR
substr()
ref
LVALUE
mefy6pfw1#
一个LVALUE是一个特殊的魔法值,当它被赋值时会执行操作。例如,调用f($hash{foo})并不会立即在%hash中创建foo条目;而是创建一个临时的LVALUE并将其作为$_[0]传递给sub。如果随后将$_[0]赋值给,则该值将存储为$hash{foo}。一个LVALUE是一个标量(也就是说,它只保存一个值),只是一个奇数类型的标量。因此,代码很可能可以通过接受SCALAR和LVALUE作为有效值来修复。但这将取决于执行检查的确切原因。也可能是这样的检查是一个逻辑错误,实际上并不需要,或者有bug。例如,ref \$_[0]不应该返回ARRAY。
f($hash{foo})
$_[0]
$hash{foo}
ref \$_[0]
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引用了其他内容。|作为标量|例外情况:
reftype( $x )
undef
$x
"ARRAY"
"HASH"
"CODE"
"GLOB"
"REGEXP"
"IO"
"FORMAT"
"INVLIST"
"REF"
"VSTRING"
"SCALAR"
REF
警告:
ref( $x )类似,它返回false(特殊标量,而不是字符串false),而不是undef。如果$x的值不是引用。如果$x是对某个祝福对象的引用,则返回该对象被祝福的包。否则,它返回与reftype( $x )相同的结果。我认为ref是reftype和blessed的混合。我总是期望有ARRAY或SCALARreftype( \$_[0] )永远不会是ARRAY。ref( \$_[0] )可以返回ARRAY,但只有当您执行类似my $x; bless( \$x, "ARRAY" ); f( $x )的奇怪操作时才可以(这就是我认为它已损坏的原因)。$_[0]总是指向标量。数组元素只能是标量。参数只能是标量。如何检查LVALUE是否代表SCALAR?它总是一个标量。在本例中,不需要reftype或ref来告诉你这一点,数组元素的值总是标量,所以$_[0]总是标量。如上所述,PVLV类型的标量会返回它。它是一种魔法标量。大多数魔法标量都是PVMG类型,但有些魔法类型会利用PVLV标量提供的额外字段。PVLV标量由$h{EXPR}作为参数返回,pos作为左值返回,substr作为左值返回,vec作为左值返回,等等。
ref( $x )
false
reftype
blessed
reftype( \$_[0] )
ref( \$_[0] )
my $x; bless( \$x, "ARRAY" ); f( $x )
$h{EXPR}
pos
substr
vec
2条答案
按热度按时间mefy6pfw1#
一个LVALUE是一个特殊的魔法值,当它被赋值时会执行操作。例如,调用
f($hash{foo})
并不会立即在%hash中创建foo条目;而是创建一个临时的LVALUE并将其作为$_[0]
传递给sub。如果随后将$_[0]
赋值给,则该值将存储为$hash{foo}
。一个LVALUE是一个标量(也就是说,它只保存一个值),只是一个奇数类型的标量。
因此,代码很可能可以通过接受SCALAR和LVALUE作为有效值来修复。但这将取决于执行检查的确切原因。也可能是这样的检查是一个逻辑错误,实际上并不需要,或者有bug。例如,
ref \$_[0]
不应该返回ARRAY。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 )
相同的结果。我认为ref
是reftype
和blessed
的混合。我总是期望有
ARRAY
或SCALAR
reftype( \$_[0] )
永远不会是ARRAY
。ref( \$_[0] )
可以返回ARRAY
,但只有当您执行类似my $x; bless( \$x, "ARRAY" ); f( $x )
的奇怪操作时才可以(这就是我认为它已损坏的原因)。$_[0]
总是指向标量。数组元素只能是标量。参数只能是标量。如何检查
LVALUE
是否代表SCALAR
?它总是一个标量。
在本例中,不需要
reftype
或ref
来告诉你这一点,数组元素的值总是标量,所以$_[0]
总是标量。如上所述,PVLV类型的标量会返回它。它是一种魔法标量。大多数魔法标量都是PVMG类型,但有些魔法类型会利用PVLV标量提供的额外字段。PVLV标量由
$h{EXPR}
作为参数返回,pos
作为左值返回,substr
作为左值返回,vec
作为左值返回,等等。