Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

How to pass two arrays to a sub?

by sanjay nayak (Sexton)
on Oct 18, 2006 at 10:12 UTC ( [id://579002]=perlquestion: print w/replies, xml ) Need Help??

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


Suggest me some suitable code for doing it. I am giving you the code below. This is not working. Plz, correct it.
Suppose #main.pl Request::aaa(@a1, @a2); package Request; sub aaa(@@) { my (@array1,@array2)= @_; }

Replies are listed 'Best First'.
Re: How to pass two lists to a sub?
by davorg (Chancellor) on Oct 18, 2006 at 10:37 UTC

    You don't have two lists, you have two arrays. Arrays and lists are different. See the FAQ What is the difference between a list and array?

    Your two arrays get flattened into a single list to be passed to the subroutine. Subroutines can only ever get one list of arguments. Inside your subroutine you try to assign the list into two array variables. But as list assignment is greedy, all of your list elements end up in @array1.

    The solution to your problem is to pass two array references to your subroutine.

    It's also worth noting that Perl subroutine prototypes are a bit of a double-edged sword. They don't really do what most people seem to expect them to do and therefore they are probably best avoided most of the time.

    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: How to pass two lists to a sub?
by blazar (Canon) on Oct 18, 2006 at 10:14 UTC
    How to pass two lists to a sub?

    You can't. But you can pass two arrayrefs. If you use the \@ prototype you can make this automatic. If anything is not clear in the documentation I pointed you to, feel free to ask for clarifications.

Re: How to pass two arrays to a sub?
by cdarke (Prior) on Oct 18, 2006 at 11:03 UTC
    I guess you would reply that you ARE using prototypes, but I doubt you are using strict and warnings. If you were then you would get "Request::aaa() called too early to check prototype".
    The @ prototype is pretty useless. It accepts a list (not just an array), a single scalar (since that is a single entry list), and even nothing, since an empty list is still a valid list.
    Yes you need to use references for this:
    use warnings; use strict; sub Request::aaa(\@\@); #main.pl my @a1 = qw (the quick brown fox); my @a2 = qw (theres more than one way); Request::aaa(@a1, @a2); package Request; sub aaa(\@\@) { my @array1 = @{shift()}; my @array2 = @{shift()}; } 1;
    Notice how the prototype has to be pre-defined, like with C/C++. Very few people like or understand prototypes, so it might be better to use:
    use warnings; use strict; #main.pl my @a1 = qw (the quick brown fox); my @a2 = qw (theres more than one way); Request::aaa(\@a1, \@a2); package Request; sub aaa { my @array1 = @{shift()}; my @array2 = @{shift()}; } 1;

    Here the caller has to know that a reference is being passed - that's the \ in front of the array (\@a1, \@a2)
Re: How to pass two arrays to a sub?
by fenLisesi (Priest) on Oct 18, 2006 at 11:26 UTC
    The code above protects your original data against changes in the called subroutine by allocating new anonymous arrays, filling them with the data from the original arrays, and only passing references to the new anonymous arrays to the subroutine. In general, that's a good thing.
      The code above protects your original data against changes in the called subroutine by allocating new anonymous arrays, filling them with the data from the original arrays, and only passing references to the new anonymous arrays to the subroutine. In general, that's a good thing.

      But it doubles the memory requirement for the arrays so it may not be an option if the arrays are large.

      --
      David Serrano

        True. I was trying to be as similar as possible to the original code to make it easier to understand.
        From the supplied question I can't really tell if the local copy is needed or not, so I played safe.
Re: How to pass two lists to a sub?
by tphyahoo (Vicar) on Oct 18, 2006 at 10:39 UTC
    use strict; use warnings; use Data::Dumper; my @list1 = qw(a b c); my @list2 = qw(d e f); printem([@list1], [@list2]); sub printem { my $list1 = shift or die "no list1"; my $list2 = shift or die "no list2"; print "list1: " . Dumper($list1); print "list2: " . Dumper($list2); }
      Please notice that
      printem([@list1], [@list2]);
      actually creates two anonymous arrays and copy data in memory, while
      printem(\@list1, \@list2)
      will pass references to the original arrays.
      Copying data will prevent accidental changes of the original arrays but may be quite long and memory-hungry if the copied data is big...
      Here's a small sample to picture the difference :
      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @list1 = qw(a b c); my @list2 = qw(d e f); sub sem { my $list1 = shift or die "no list1"; my $list2 = shift or die "no list2"; $list1->[0]='x'; @{$list2}=qw(D E F); } # print original data print "list1: " . Dumper(@list1); print "list2: " . Dumper(@list2); # call with copy sem([@list1], [@list2]); print "list1: " . Dumper(@list1); print "list2: " . Dumper(@list2); # call by reference sem(\@list1, \@list2); print "list1: " . Dumper(@list1); print "list2: " . Dumper(@list2);
        Hi
        Thanks a lot for your suggestion.
        Regd's
        Sanjay

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://579002]
Approved by prasadbabu
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (5)
As of 2024-04-16 17:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found