Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

passing array references

by cosmicperl (Chaplain)
on Dec 04, 2004 at 14:01 UTC ( #412402=perlquestion: print w/replies, xml ) Need Help??

cosmicperl has asked for the wisdom of the Perl Monks concerning the following question:

  This is something that has bothered me for a while, I'm suer there is a better way to do it.
I'm returning some scalars and array references:-
return ($scalar, \@array, $scalar1, \@array2);
I want to load them directly into other arrays and scalars. At the moment the only way I can do it is like this:-
my ($scalar, $tmparray, $scalar1, $tmparray2) = subroutine; my @array = @$tmparray; my @array2 = @$tmparray2;
Sometimes I'm passing a lot of values, so this way get's long winded. I'm sure there is a way to do it in a single line. Your perl wisdom is welcome.

P.S. Sometimes I'm passing the scalars as references as well. I want them loaded into normal scalars.

Replies are listed 'Best First'.
Re: passing array references
by Fletch (Bishop) on Dec 04, 2004 at 14:28 UTC

    You could turn the problem around and instead of returning references to results pass in references to where you want the results stored.

    sub foo { my( $s, $a, $s1, $a2 ) = @_; ${$s} = 42; @{ $a } = 0..5 ${$s1} = sin( 1 ); @{ $a2 } = qw( yadda yadda yadda ); return; } foo( \$a, \@b, \$c, \@d );

    Update: Oop, left off making scalars references as well

      I like this approach because it allows for some nice sanity checking too (I know it is only 1 array_ref, but it is the principle)
      sub get_my_list { my $array_ref = $_; if( &some_other_func() ){ @{$array_ref} = qw( Yadda yAdda yaDda ); return 1; } return 0; } if( get_my_list(\@array) ){ print 'I got this array: '.join(',',@array); }else{ print 'Failed'; }
      But leading back to your original question, my initial thoughts would also be to use a hash_ref. Your scalar-array data pattern lends itself well to a hash. And if the hash key (scalar) is a key to a particular function that you wish to perform on the array then your method becomes easily scalable.
Re: passing array references
by gaal (Parson) on Dec 04, 2004 at 14:35 UTC
    Why not use indirect syntax to access the data via the reference?

    Saying my @array = @tmparray actually allocates new memory and makes a (shallow) copy of the data. Sometimes this is what you want, but in those cases it does make sense to actually say so explicitly. If you don't need a copy, and are just looking for convenience, access the elements as $arrayref->[0] and so on. True, this looks different from $array[0], but that's because it is different.


    Okay, okay, if you're *sure* you want to do this, here's how to create an alias of the referenced data (-:

    $arrayref = [ qw/A B C D/ ]; { no strict "vars"; *array_alias = $arrayref; } print $array_alias[0];
    Update: Fletch's advice is very good. Heed it and avoid this kludgery, at least until you really need it.
Re: passing array references
by Zed_Lopez (Chaplain) on Dec 04, 2004 at 16:20 UTC

    Also, there's not any harm in leaving them as references and using them that way (unless you really hate typing -> and prefixing it with @ as appropriate).

Re: passing array references
by Prior Nacre V (Hermit) on Dec 05, 2004 at 05:55 UTC

    The following is an abstraction that shows a way to do what you want. It will handle "... a lot of values ..." and can be extended (e.g. you could add support for hashrefs at some later time).

    [ ~/tmp ] $ cat return_multi_refs # return_multi_refs use strict; use warnings; use constant REF_SYM_MAP => { '' => ['$', '', ''], SCALAR => ['$', '${', '}'], ARRAY => ['@', '@{', '}'], }; my $rh_params = subroutine(); spawn_vars($rh_params); { no strict qw(vars); no warnings qw(once); print "scalar1 [$scalar1]\nscalar2 [$scalar2]\nscalar3 [$scalar3]\ +n", "array1[1] [$array1[1]]\narray2[2] [$array2[2]]\n"; } exit; sub subroutine { my @array1 = ( qw(a b c ) ); my $ra_array2 = [ qw(x y z) ]; my $scalar2 = 'Scalar the Second'; my $scalar3 = 'Scalar the Third'; my %params = ( scalar1 => 'Scalar the First', array1 => \@array1, scalar2 => \$scalar2, array2 => $ra_array2, scalar3 => $scalar3, ); return \%params; } sub spawn_vars { eval join '', map {( REF_SYM_MAP->{ref($_[0]->{$_})}[0], __PACKAGE__, '::', $_, + ' = ', REF_SYM_MAP->{ref($_[0]->{$_})}[1], '$_[0]->{', $_, '}', REF_SYM_MAP->{ref($_[0]->{$_})}[2], ';', )} keys(%{$_[0]}); die $@ if $@; }

    Test output:

    [ ~/tmp ] $ perl return_multi_refs scalar1 [Scalar the First] scalar2 [Scalar the Second] scalar3 [Scalar the Third] array1[1] [b] array2[2] [z] [ ~/tmp ] $



Re: passing array references
by roho (Bishop) on Dec 06, 2004 at 09:09 UTC
    I agree with gaal -- heed Fletch's advice.

    "Its not how hard you work, its how much you get done."

Re: passing array references
by educated_foo (Vicar) on Dec 09, 2004 at 23:30 UTC
    People here tend to frown on this sort of thing, but you can use globs:
    sub f { return \'hello', [1..3], { a => b }, \&f } local (*a, *b, *c, *g) = foo(); # $a, @b, %c, and &g are now defined.
A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://412402]
Approved by zejames
Front-paged by NetWallah
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (2)
As of 2023-09-26 15:26 GMT
Find Nodes?
    Voting Booth?

    No recent polls found