TopCoder
TopCoder

Reputation: 4296

What is wrong in this Perl expression?

What's the problem with following. I am getting $attribute not defined error.

if (my $attribute = $Data->{'is_new'} and $attribute eq 'Y') {
}

Upvotes: 7

Views: 299

Answers (4)

bdonlan
bdonlan

Reputation: 231471

You're being too clever. Just do this:

my $attribute = $Data->{'is_new'};

if (defined $attribute && $attribute eq 'Y') { ... }

The problems are twofold:

  • You have an extra ) in your if
  • my in expression context binds very tightly; $attribute is not in lexical scope until the body of the conditional statement that contains it, so the other branch of the and cannot access it. You need to lift it to the containing context, as in my example.

Upvotes: 10

TLP
TLP

Reputation: 67940

Like has already been mentioned, you cannot declare a variable and use it at the same time. That's just the way it is; You need to finish the declaration statement before you can use the new variable.

What you could have done though, and I am frankly somewhat lost as to why this has not been mentioned yet, is this:

if (my $attribute = $Data->{'is_new'} and $Data->{'is_new'} eq 'Y') 

$attribute is not yet declared, but $Data->{'is_new'} is.

Just to be clear: The point of this if statement would then be three things:

  • Initialize and assign a value to $attribute
  • Check that this value is not undefined/empty string/zero
  • Check if this value is 'Y'

The lexical scope of $attribute is the inside of the if-statements subsequent block, no more, no less.

Upvotes: 0

flesk
flesk

Reputation: 7589

The other answers are good. I just want to add that if you want to avoid cluttering the surrounding scope with the $attribute variable you could do:

if (($Data->{'is_new'} || '') eq 'Y') {
    # do stuff
}

This also works with strict and warnings.

Upvotes: 1

ikegami
ikegami

Reputation: 386706

use strict; would have found the problem.

$ perl -e'use strict; my $attribute = "..." and $attribute eq "Y";'
Global symbol "$attribute" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.

A my declaration only has an effect on subsequent statements, not the the statement in which the declaration is is located. (Same goes for the our and local declarations.) That means the $attribute that you create with my and to which you assign is a different variable than the $attribute you compare to Y. You want

my $attribute = $Data->{'is_new'};
if ($attribute eq 'Y') { ... }

Now, if $Data->{is_new} doesn't exist or is undefined, $attribute will be undefined, and comparing it to Y will issue a warning. You can avoid this warning as follows:

my $attribute = $Data->{'is_new'};
if (defined($attribute) && $attribute eq 'Y') { ... }

Alternatively: (5.10+)

my $attribute = $Data->{'is_new'};
if (($attribute // '') eq 'Y') { ... }

Upvotes: 10

Related Questions