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

I am not sure why it fails everytime. Even if arrays are equal, it always returns 0. If I do this without sub routine, it works. Is there something wrong in the sub function?

@a = (5,10,15); @b = (5,10,15); $num = &arrayComp(@a, @b); print "num - $num\n"; sub arrayComp(@a, @b) { my(@a, @b) = @_; if (@a != @b) { $equals = 0; } else { $equals = 1; foreach (my $i = 0; $i < @a; $i++) { if ($a[$i] != $b[$i]) { $equals = 0; last; } } } return $equals; }

Please help. Thanks!

Replies are listed 'Best First'.
Re: Array comparison doesn't work
by davido (Cardinal) on Nov 23, 2013 at 18:55 UTC

    You double-posted this (Reaped: Array comparison doesn't work). Remember it can take a few minutes for a post to be approved.

    As for your problem, arrays flatten when passed as parameters. You should be passing array references instead, to maintain the original containers.

    Please see perlsub for details. No point re-stating everything it says unless there's some aspect of that POD that needs clarification. But in brief:

    sub flattened { my( @a, @b ) = @_; return @a; # Returns everything. } sub preserved { my( $a_aref, $b_aref ) = @_; return @$a_aref; # Returns only the stuff contained in @$a_aref. } my @this = qw( 1 2 3 ); my @that = qw( 4 5 6 ); print "$_\n" for flattened( @this, @that ); # prints 1 2 3 4 5 6. print "$_\n" for preserved( \@this, \@that ); # prints 1 2 3.

    Dave

      I am sorry. Didn't realize it double posted but thanks for making this array confusion clear for me!
Re: Array comparison doesn't work
by choroba (Cardinal) on Nov 23, 2013 at 18:57 UTC
    You cannot unflatten two arrays from the parameter array. If you want to pass two arrays to a subroutine, use a reference:
    arrayComp(\@a, \@b); sub arrayComp { my ($aref, $bref) = @_; my @a = @$aref; my @b = @$bref;

    Moreover, what do you think using (@a, @b) in the parameter list does?

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanks for your help! I was just passing in array like I was passing in variables. I didn't think there would be much difference but thanks for pointing it out.
Re: Array comparison doesn't work
by CountZero (Bishop) on Nov 24, 2013 at 08:40 UTC
    To give you the full picture, it is possible to pass arrays as parameters and circumvent the flattening of those arrays.

    That involves using subroutine prototypes and is probably one of the few acceptable uses of prototypes .

    It goes as follows:

    use Modern::Perl; sub two_arrays (\@\@) { my @first = @{$_[0]}; my @second = @{$_[1]}; say "First array: @first"; say "Second array: @second"; } my @one = qw/een twee drie/; my @two = qw/nung song saam/; two_arrays(@one, @two);
    Output:
    First array: een twee drie Second array: nung song saam
    The prototype (\@\@) means that this subroutine takes two arrays as parameters and a reference to those two arrays will passed to the sub. This "referencing" will happen automatically and of course it means that you must dereference it inside of your sub.

    It is not the usual or expected mode of operation of using subroutines and you better document this very clearly or people will get quite confused. But it is there if you want it.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: Array comparison doesn't work
by Laurent_R (Canon) on Nov 23, 2013 at 19:03 UTC

    Not much to add, except that it is the same if you want to return two or more arrays from a subroutine: you also need to return references to those arrays, otherwise the arrays get flattened into one single array.