3

I am trying to check if an element is defined, using defined function in Perl.

Code :

$mylist[0][0]="wqeqwe";
$mylist[0][1]="afasf";
$mylist[1][0]="lkkjh";

print scalar(@mylist), "\n";

if (defined($mylist[2][0])){print "TRUE\n";}

print scalar(@mylist), "\n";

Output

2
3

Before using defined function, there were two elements in first dimension of @myarray. After using defined function, the number of elements increase to 3.

How to use defined function with out adding new elements ?

384X21
  • 6,553
  • 3
  • 17
  • 17

5 Answers5

7

First check that the first-level reference exists.

if ( defined($mylist[2]) && defined($mylist[2][0]) ) {
    print "TRUE\n";
}

What you've encountered is called autovivification: under some circumstances, Perl creates complex data structures when you use them as if they already existed.

Tim
  • 13,904
  • 10
  • 69
  • 101
5

It's interesting to note that there's a non-core pragma called autovivification, and that if you run your code under no autovivification; your problem will go away.

hobbs
  • 223,387
  • 19
  • 210
  • 288
3

When you refer to $mylist[2][0], perl's autovivification creates the array element $mylist[2].

To prevent this, you can check this element first:

if ( (defined $mylist[2]) && (defined $mylist[2][0]) )
TLP
  • 66,756
  • 10
  • 92
  • 149
3
defined($mylist[2][0])

is equivalent to

defined($mylist[2]->[0])

which is short for

defined( ( $mylist[2] //= [] )->[0])

due to autovivification. You can disable autovivification using the autovivification pragma.

no autovivificatoin;
if (defined($mylist[2][0]))

Or you can avoid evaluating code that would trigger it.

if (defined($mylist[2]) && defined($mylist[2][0]))
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • 1
    It really sucks that the spell checker doesn't recognise "autovivification" because it's so easy to misspell! :) – ikegami Jun 27 '12 at 17:51
  • Just curious : If `defined(mylist[2][0])` adds new element by [autovivification](http://search.cpan.org/perldoc?autovivification), why isn't print statement after `defined(mylist[2][0])` returning `TRUE` ? – 384X21 Jun 27 '12 at 17:59
  • 3
    @user1029725 `defined($mylist[2][0])` creates the `$mylist[2]` element. `$mylist[2][0]` is still undefined. You can check to make sure with Data::Dumper if you want to. – Tim Jun 27 '12 at 18:01
  • The first element of the empty array created through autovivification is not defined, since it doesn't even exist. – ikegami Jun 27 '12 at 20:00
2

Actually because it's autovivification, you can check it easily with Data::Dumper, before and after using defined.

use Data::Dumper;
my @mylist;

$mylist[0][0]="wqeqwe";
$mylist[0][1]="afasf";
$mylist[1][0]="lkkjh";

print Dumper(@mylist);

Output before

$VAR1 = ['wqeqwe', 'afasf'];
$VAR2 = [ 'lkkjh'];


print Dumper(@mylist);

Output after

$VAR1 = [ 'wqeqwe','afasf' ];
$VAR2 = ['lkkjh'];
$VAR3 = [];
Pavel Vlasov
  • 3,455
  • 21
  • 21
  • 1
    You should use a reference as argument to `Dumper`, e.g. `print Dumper \@mylist`. It will keep the array structure intact and make it more readable. (You should also format your answer so we can see the structure.) – TLP Jun 27 '12 at 17:47