in reply to array reference madness

Your array @tmp holds a single array reference, not a list of values — you probably meant

my @tmp = @{${$$ref}[3]};

which can also be written as

my @tmp = @{$$ref->[3]};

BTW, I don't know what the exercise is, but I can't help thinking you have one level of referencing too much... :)

Replies are listed 'Best First'.
Re^2: array reference madness
by Porculus (Hermit) on Mar 14, 2009 at 21:44 UTC

    Indeed; the extra referencing is being added by the \&buildlist($_), which is an unnecessary complication. There's no need to build a reference here at all, since buildlist() already explicitly returns one, and it's arguably confusing because \& is normally used to take a reference to a subroutine, not to a return value.

    Removing the \& there would enable all the ${$$...}-type constructions to be simplified, so for example the assignment to @tmp would then become just @{$ref->[3]}. This is probably a Good Thing.

      "Extra-referencing?!!" I was thinking the \& and the \@ matched, wrt the "type" of the return value. So you've given me something to think about -- I'll try and apply this. Thanks much! ps. the exercise is 5-2. I like the book, it's well structured ;)
        use O qw' Deparse -p '; print \&reference; # real ref print \&call(1); # ref to return value print \( &call(1) ); # same as above, ref to return print \( call(1) ); # same as above, ref to return __END__ print((\&reference)); print(\(&call(1))); print(\(&call(1))); print(\(call(1))); __DATA__
Re^2: array reference madness
by halfcountplus (Hermit) on Mar 15, 2009 at 02:08 UTC
    For some reason I must have thought that \& was the correct way to return a reference...anyway it worked out neatly:
    #!/usr/bin/perl -w use strict; my %all; open(INPUT,"<coconet.dat") || die "Can't open coconet.dat"; while (<INPUT>) { if ($_ =~ /^#/) { next } my ($src, $dest, $bytes) = split; # hash of hashes holds the from->to transmission TOTALS; we do not + keep all the data $all{$src}{$dest}+=$bytes; } close(INPUT); # simple use of map to create array of references to hashes: my @refli +st = map { \%{$all{$_}} } keys %all; # so...create an array of references to arrays (from map callback) of +scalars and REFS TO existing hashes and new anonymous arrays! my @reflist = sort { $$b[2] <=> $$a[2] } map buildlist($_), keys %all; + # sort by the total of TOTALS foreach my $ref (@reflist) { print "$$ref[0] $$ref[2]\n"; # the next two are the same: foreach my $line (@{$ref->[3]}) { print "\t$line ${$ref->[1]}{$li +ne}\n" } # foreach my $line (@{$$ref[3]}) { print "\t$line ${$$ref[1]}{$lin +e}\n" } } sub buildlist { my $site = $_; my @tmp; $tmp[0]=$site; $tmp[1]=\%{$all{$site}}; foreach (keys %{$tmp[1]}) { $tmp[2]+=${$tmp[1]}{$_} } # make element 3 a reference to an anonymous array of scalars (the + dest site names, ranked) @{$tmp[3]} = sort { ${$tmp[1]}{$b} <=> ${$tmp[1]}{$a} } keys %{$tm +p[1]}; return \@tmp; # 0=site name, 1=hash ref, 2=total bytes for all t +ransmissions from site, 3=ranked dest names ref } __DATA__ 2000 lines, eg: gilligan.crew.hut lovey.howell.hut 4721 thurston.howell.hut lovey.howell.hut 4046 professor.hut ginger.girl.hut 5768 gilligan.crew.hut laser3.copyroom.hut 9352 gilligan.crew.hut maryann.girl.hut 1180 fileserver.copyroom.hut thurston.howell.hut 2548 skipper.crew.hut gilligan.crew.hut 1259
    This is more complex, but no longer than the solution in the book -- but the solution in the book does not create a permanent data structure either (goal was to just print ranked totals).
      # the next THREE are the same: # foreach my $line (@{$ref->[3]}) { print "\t$line ${$ref->[1]}{$line} +\n" } # foreach my $line (@{$$ref[3]}) { print "\t$line ${$$ref[1]}{$line}\n +" } foreach my $line (@{$$ref[3]}) { print "\t$line $all{$$ref[0]}{$line}\ +n" } }
      Notes ;)