An overloaded String variable is considered defined no matter what

I have the following lines in a script:

my $spec = shift;
if (!defined $spec) {
    return ("Invalid specification", undef);
}
$spec = "$spec" // '';

Naturally, I would expect this when I passed undef, return the warning Invalid specificationto the array, and the second element - undef. Instead, the check is passed, and I get a console message warning me about Use of uninitialized value $spec in stringon the next line.

$specis an object with overloading strings and numbers and, unfortunately, is written in such a way that an attempt to verify the likelihood in this particular subprogram (for example if ($spec)) leads to deep recursion and segfault.

While I'm interested in why this is happening, I'm more interested in how to stop it. I want to exclude a warning about the console, preferably without no warnings qw/uninitialized/. Is this possible, and if so, how to do it?

+4
source share
1 answer

You say that $specthis is an object with line overloading .

If this is the case, then you need to force it into the String form before checking its definition:

if (! defined overload::StrVal($spec)) {

Correction for ysth

As ysth pointed out in StrVal, it does not force overloaded stanza:

Overload :: StrVal (Arg)

arg, . , ( , ), Scalar:: Util:: refaddr(), .

, , :

"$ spec" var. , undef.

:

#!/usr/bin/env perl

use strict;
use warnings;

use Test::More tests => 2;

my $obj_str_defined = StringOverloaded->new("has value");
my $obj_str_undef   = StringOverloaded->new(undef);

ok( is_overloaded_string_defined($obj_str_defined), qq{\$obj_str_defined is defined} );
ok( !is_overloaded_string_defined($obj_str_undef),  qq{\$obj_str_undef is undef} );

sub is_overloaded_string_defined {
    my $obj = shift;

    my $is_str_defined = 1;

    local $SIG{__WARN__} = sub {
        $is_str_defined = 0 if $_[0] =~ /Use of uninitialized value \$obj in string/;
    };

    my $throwaway_var = "$obj";

    return $is_str_defined;
}

{
    # Object with string overloading
    package StringOverloaded;

    use strict;
    use warnings;

    use overload (
        '""' => sub {
            my $self = shift;
            return $$self;    # Dereference
        },
        fallback => 1
    );

    sub new {
        my $pkg  = shift;
        my $val  = shift;
        my $self = bless \$val, $pkg;

        return $self;
    }
}

:

1..2
ok 1 - $obj_str_defined is defined
ok 2 - $obj_str_undef is undef
+7

Source: https://habr.com/ru/post/1657919/


All Articles