lost in an array of array references...

M

msbrentlinger

please help.. im just now getting into references and im so very lost.

the following code

use strict;
use warnings;
my @src_dbs = qw(a b c); # add more dbs to compare to here
my @data_src;
foreach (@src_dbs){
print "getting data from db $_\n";
push @data_src, &get_db_data($_);
}
print "\nthere are ",scalar(@data_src)," arrays\n";
print "\narray one has ",scalar($data_src[0])," items\n"; # <<< __i
think this is my problem, but how should i refer to this array to get
the # of items correctly ?
foreach (@data_src){
print "\ndb $$_[3] data (ref to with $_) has ",scalar(@$_)," items,
which are: @$_";
}
sub get_db_data {
my @a = qw(1 2 3);
push @a, $_;
push @a, '5' if $_ eq 'c'; # test for bad data
return (\@a);
}


returns

getting data from db a
getting data from db b
getting data from db c
there are 3 arrays
array one has ARRAY(0x186932c) items
db a data (ref to with ARRAY(0x186932c)) has 4 items, which are: 1 2 3
a
db b data (ref to with ARRAY(0x18691f4)) has 4 items, which are: 1 2 3
b
db c data (ref to with ARRAY(0x18692cc)) has 5 items, which are: 1 2 3
c 5


when id rather it return


getting data from db a
getting data from db b
getting data from db c
there are 3 arrays
array one has 4 items
db a data (ref to with ARRAY(0x186932c)) has 4 items, which are: 1 2 3
a
db b data (ref to with ARRAY(0x18691f4)) has 4 items, which are: 1 2 3
b
db c data (ref to with ARRAY(0x18692cc)) has 5 items, which are: 1 2 3
c 5



i know im just not referring to my array right to get a number of items
for array one. but everything i try just results in errors. appearantly
i just dont understand. any advice would be greatly appreciated
 
P

Paul Lalli

please help.. im just now getting into references and im so very lost.

the following code

use strict;
use warnings;
Excellent!!

my @src_dbs = qw(a b c); # add more dbs to compare to here
my @data_src;
foreach (@src_dbs){
print "getting data from db $_\n";
push @data_src, &get_db_data($_);

In general, don't call subroutines with the & unless you know what that
does and you want those two effects. (Here, you don't). Just elminate
the & from that line.
}
print "\nthere are ",scalar(@data_src)," arrays\n";
print "\narray one has ",scalar($data_src[0])," items\n"; # <<< __i
think this is my problem, but how should i refer to this array to get
the # of items correctly ?

You are correct, that is a problem. $data_src[0] is a reference to an
array. In order to dereference an array reference, you surround the
reference in { }, and prepend a @ symbol:

print "array one has ", scalar ( @{$data_src[0]} ), "items\n";

You may be getting confused by the common shortcut that if the
reference is itself a single simple scalar variable (as opposed to an
element of an array, like in this case), you are allowed to drop the {
}. You are not allowed to do so in any other case.
foreach (@data_src){
print "\ndb $$_[3] data (ref to with $_) has ",scalar(@$_)," items,
which are: @$_";

I personally dislike the $$ notation, and prefer to use the arrow rule
that says I can drop one of the $, and insert an arrow between the
reference and the index:

print "db $_->[3] data (ref to with $_) has ", scalar(@{$_}), "items,
which are @{$_}\n";

(fwiw, _Perl Best Practices_ recommends never using the double-sigils,
even when you're allowed to. If you're accessing an element of the
referenced array, use the arrow notation. If you're accessing the
whole thing, keep the { }, even if you're allowed to drop them.)
}
sub get_db_data {
my @a = qw(1 2 3);
push @a, $_;

Whoa whoa whoa. Be careful here. This *works*, but almost by
accident. $_ happens to have the value it had when you called
get_db_data because the foreach loop implicitly local'izes the value.
Don't rely on that. You passed $_ to the subroutine, and quite
rightfully so. So in your subroutine, get use the list of arguments,
which is stored in @_:

sub get_db_data {
my ($arg) = @_;
my @a = qw/1 2 3/;
push @a, $arg;
push @a, '5' if $_ eq 'c'; # test for bad data

push @a, '5' if $arg eq 'c';
return (\@a);
}
i know im just not referring to my array right to get a number of items
for array one. but everything i try just results in errors. appearantly
i just dont understand. any advice would be greatly appreciated

Keep a few facts in mind:

* Evaluating an array in scalar context is the way to get the size of
the array. If you only have a reference to the array, you'll need to
dereference that reference first.
* If you have a refernece to an array, derefernece the reference by
surrounding it in curly-braces and prepending an @ sign.
* You are only allowed to drop the braces if and only if the reference
itself is a single simple scalar variable. Even if you are allowed,
it's more readable and understandable (IMO, anyway) not to drop them.

See also:
perldoc perlreftut
perldoc perllol

Hope this helps,
Paul Lalli
 
M

msbrentlinger

Paul,
All very insghtful and informative tips. Thanks so much for the help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,990
Messages
2,570,211
Members
46,796
Latest member
SteveBreed

Latest Threads

Top