简体   繁体   中英

How to check if LVALUE represents SCALAR

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 or SCALAR

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 represents SCALAR 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM