Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

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:

Hi,
  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.

Lyle
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 ] $

    Regards,

    PN5

Re: passing array references
by roho (Chancellor) 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?
Username:
Password:

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
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2022-06-28 00:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My most frequent journeys are powered by:









    Results (89 votes). Check out past polls.

    Notices?