AtomicPorkchop
AtomicPorkchop

Reputation: 2675

Why does this statment return true

Why does this statement,

    if (! $ssh_options{user}) {

    delete $ssh_options{user};

}

return true, but this statement

    if ($ssh_options{user} eq 'undef') {

    delete $ssh_options{user};

}

give me the error,

Use of uninitialized value $ssh_options{"user"} in string eq at analyze.pl line 230.

I thought you always had to have something for perl to compare the value of the variable being compared.

** Update **

@ Quick Joe Smith

I cannot base my comparison on whether the hash keys exist or not because the values for this hash

sub ssh_connect {

my $host = shift;

my %ssh_options = (

    port => shift,
    user => shift,
    password => shift

    );

Come from this function which calls the sub routine

        if ((exists $config_file{user}) && (exists $config_file{password})) {

        my $vmware_user = $config_file{user};

        my $vmware_password = $config_file{password};

        ssh_connect($vmware_host, $vmware_port, $vmware_user, $vmware_password);

    } else {

        ssh_connect($vmware_host, $vmware_port);

    }

Upvotes: 0

Views: 163

Answers (4)

DavidO
DavidO

Reputation: 13942

With Perl, undefined evaluates to false in Boolean context. So your first test 'works' as you expect. However, it might introduce a bug if zero or an empty string is a legitimate value for $ssh_options{user} to hold, if you don't wish to treat that the same as undef. That's because your first test doesn't differentiate between false as a value, and false as undefined. As far as Perl's Boolean evaluation goes, all of the following are "false": 0, '' (empty string), undef, or an empty list.

Your second snippet of code fails because undef should be a bareword, not a quoted string. 'undef' as a quoted string IS a value, which would actually evaluate to 'true' in Boolean tests. Because you're comparing an actual value to your hash element, Perl warns you that you're comparing something to an undefined value. In this case, the undefined value is $ssh_options{user}. It's actually good that Perl is warning you; it's given you a clue as to what you're doing wrong.

If you really want to test whether $ssh_options{user} is defined, use the defined() function. If you want to test whether $ssh_options{user} exists, use the exists() function.

Upvotes: 0

Quick Joe Smith
Quick Joe Smith

Reputation: 8222

Use exists for checking hash keys.

if (exists $ssh_options{user}) {
    ...
}

However, in your case, it seems as though you're checking for existing keys whose values may be undefined, in which case:

if (defined $ssh_options{user}) {
    ...
}

The above may be what you want.


As a sidenote, checking to see if the value of any variable is defined in the way you described:

if ($something eq 'undef') {
    ...
}

Is wrong. You're checking to see if the variable contains the string "undef". What you need in those situations is:

unless (defined $something) {
    ...
}

Upvotes: 2

Eric Strom
Eric Strom

Reputation: 40142

Perl hash slots have a number of ways they can be false. If the key has never been filled, the exists function will return false. If the key exists but contains an undefined value, exists will be true but the defined function will return false. In normal boolean context, as given by an if statement, a hash key that was never filled, or is undefined, '', 0 or anything that reduces to those will be false.

From your update, it sounds like what you want is to use defined

delete $ssh_options{user} unless defined $ssh_options{user};

Upvotes: 2

Andrew Cooper
Andrew Cooper

Reputation: 32576

But if $ssh_options{"user"} is uninitialized then it it doesn't have a value to compare to.

Upvotes: 1

Related Questions