For years, I am using a code that contains the following condition
ref \$_[0] eq 'SCALAR'
I always expect there an ARRAY
or SCALAR
, but recently I passed substr()
into that parameter. Unexpected things happened. The condition returned a false value.
Then I figured it out. The ref
returned LVALUE
instead of SCALAR
.
Since LVALUE
is a weird type of reference, I need to check if a scalar is behind it.
How can I check is this LVALUE
represents SCALAR
or not?
An LVALUE is a special magical value that takes action when it is assigned to. So for example, calling f($hash{foo})
doesn't immediately create the foo entry in %hash; instead a temporary LVALUE is created and passed to the sub as $_[0]
. If $_[0]
is subsequently assigned to, that value gets stored as $hash{foo}
.
An LVALUE is a scalar (ie it holds a single value), just an odd type of scalar.
So it's likely that the code can be fixed by just accepting both SCALAR and LVALUE as valid values. But it will depend on exactly why the check is done. It may also be that such a check is a logic error and is not actually needed, or is buggy. For example ref \$_[0]
should never return ARRAY.
Values that can be returned by reftype( $x )
(from Scalar::Util) in Perl 5.36:
Value | Description | Can be dereferenced? |
---|---|---|
undef |
The value of $x isn't a reference. |
No |
"ARRAY" |
$x reference an array (a scalar of type PVAV. |
As an array |
"HASH" |
$x reference a hash (a scalar of type PVHV). |
As a hash |
"CODE" |
$x reference a sub (a scalar of type PVCV). |
As a sub |
"GLOB" |
$x reference a glob (a scalar of type PVGV). |
As a glob, scalar, array, hash or code |
"LVALUE" |
$x references a scalar of type PVLV, with some exceptions. |
As a scalar |
"REGEXP" |
$x references a scalar that's a compiled regexp pattern (a scalar of type REGEXP). |
As a scalar |
"IO" |
$x references a scalar that's an IO object (a scalar of type PVIO). |
No |
"FORMAT" |
$x references a scalar of type PVFM. I don't know if it's possible to get a reference to a format. |
No |
"INVLIST" |
$x references a scalar of type INVLIST. This is an internal type. You should never see this. |
No |
"REF" |
$x references a scalar that contains a reference. |
As a scalar |
"VSTRING" |
$x references a scalar that contains a version string. |
As a scalar |
"SCALAR" |
$x references something else. |
As a scalar |
Exceptions:
SCALAR
is returned for reference to a tied PVLV.REF
is returned for reference to a PVLV containing a reference.Warnings:
REF
is returned for magical variables that currently contain a reference, and SCALAR
for those that don't. But the value of magical variables can change every time you fetch it. ref( $x )
is similar. It returns false
(the special scalar, not the string false
) instead of undef
if the value of $x
isn't a reference. If $x
is a reference to something blessed, it returns the package into which it is blessed. Otherwise, it returns the same as reftype( $x )
. I consider ref
a broken mix of reftype
and blessed
.
I always expect there an
ARRAY
orSCALAR
reftype( \$_[0] )
will never be ARRAY
.
ref( \$_[0] )
can return ARRAY
, but only if you do something weird like my $x; bless( \$x, "ARRAY" ); f( $x )
my $x; bless( \$x, "ARRAY" ); f( $x )
my $x; bless( \$x, "ARRAY" ); f( $x )
. (And that's why I consider it broken.)
$_[0]
is always going to a scalar. Array elements can only be scalars. Arguments can only be scalars.
How can I check is this
LVALUE
representsSCALAR
or not?
It's always a scalar.
In your case, you don't need reftype
or ref
to tell you that. The value of array elements are always scalars, so $_[0]
is always going to be a scalar.
As per above, it's returned for scalars of type PVLV. It's a type of magical scalar. Most magical scalars are of type PVMG, but some types of magic take advantage of the extra fields provided by a PVLV scalar. PVLV scalars are returned by $h{EXPR}
as an argument, pos
as lvalue, substr
as lvalue, vec
as lvalue, and more.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.