in reply to Passing Array of Arrays

When you're passing arrays and hashes into and out of subs, it's (normally) necessary to pass a reference to the array, rather than the array itself.

If you don't pass a reference, the array is flattened, and passed out as a simple list - not something you want in this case.

You can correct this by having the GetLogFilesAndDatesIntoArray sub return a reference to the AoA, rather than trying to flatten the AoA and then return it. This is easy to do - just change the return to return \@filesanddates;.

Once you have the sub returning a reference, you should assign it to a scalar variable, rather than an array (a reference is always a scalar, regardless of what it refers to), and you can then use this variable to pass the array into the ExtractData sub - like this:

# note: $datalist now, it's a reference $datalist = GetLogFilesAndDatesIntoArray($logdirectory); ExtractData($datalist); # passes the reference into the sub

Finally, once you have the reference going into the ExtractData sub, you can deference it to retrieve the original array like this:

my $_filesanddates = shift; @filesanddates = @$_filesanddates; # dereferences the reference

There's a whole load of stuff on references and subroutines in perlsub and perlref.

Update: Thanks to broquaint for pointing out that I'm talking absolute rubbish .. oh well, eh. References are still a Good Thing in my book, but I guess that's a preference now, rather than a requirement...

Hope that helps a little ...
-- Foxcub
A friend is someone who can see straight through you, yet still enjoy the view. (Anon)
All code is untested unless explicitly stated otherwise.

Replies are listed 'Best First'.
Re: Re: Passing Array of Arrays
by broquaint (Abbot) on Mar 11, 2003 at 13:15 UTC
    If you don't pass a reference, the array is flattened, and passed out as a simple list - not something you want in this case.
    Er, wha? This is a perfectly valid case to pass a list back and forth. Since the code is only dealing with a single array this is not an issue, it would be an issue however if multiple arrays were being passed about e.g
    sub f { print "got: ", @_, $/ } my @a = qw( one two three ); my @b = qw( four five six ); ## @a & @b will be flattened into a single list f(@a, @b); ## pass references to keep array integrity f(\@a, \@b); ## only @a is passed, so only @a is received f(@a); __output__ got: onetwothreefourfivesix got: ARRAY(0x8107e50)ARRAY(0x8107f34) got: onetwothree

    HTH

    _________
    broquaint

      Eh?

      I was always told that "complex" structures (anything other than a "simple" array or hash - and the OP is talking about an AoA) got flattened, and that its integrity wasn't necessarily preserved when it was passed into and out of a sub.

      I'm quite happy to be wrong, though .. that's been a pet peeve of mine with Perl for *ages* ... *grin* ..

      My thinking this (probably) comes from perlsub ..

      Perl sees all arguments as one big, long, flat parameter list in @_. Like the flattened incoming parameter list, the return list is also flattened on return.

      I read this as saying that if I have a crazily bizarre structure, such as an AoA or AoH or whatever, its integrity and structure will not necessarily be preserved - epecially not if it becomes a simple list of scalars.

      Can anyone clarify this? I'm gonna play with some code, see what happens ..

      Update: Ok, so code playing proves I'm completely wrong ... all kudos to broquaint - I've learnt something completely new today .. and got rid of a pet hate :)

      -- Foxcub
      A friend is someone who can see straight through you, yet still enjoy the view. (Anon)

        Right, in list context an arrays and hashes are flattened into a single list e.g
        my @a = qw( foo bar baz ); my %h = qw( one ichi two ni ); ## print evaluates it's args in list context print "array: ", @a,$/; print "hash: ", %h,$/; print "a & h: ", @a, %h, $/; __output__ array: foobarbaz hash: oneichitwoni a & h: foobarbazoneichitwoni
        Now with nested data structures this is still exactly the same as references aren't automagically dereferenced e.g
        my @a = ( ["one"], ["two"] ); my %h = ( a => \@a ); print "array: ", @a, $/; print "hash: ", %h, $/; __output__ array: ARRAY(0x80fbb0c)ARRAY(0x80fba1c) hash: aARRAY(0x8107d84)
        So because subroutines' arguments are evaluated in list context an AoA is fine and dandy to pass about without having to create a reference to it.
        HTH

        _________
        broquaint

        When you build an AoA, you're just building an array, who's values are references to other arrays. So while you write:

        @a = ( [ qw/1 2 3/ ], [ qw/a b c/ ] );
        You're actually creating 3 arrays, and put in @a references to the other two.

        So when you pass that to a sub, it's passed as a simple list - but the members of the list are still the references to your two arrays, and perl doesn't really care if they're scalars or references - there's no automatic-recursive-dereferencing going on...

        Does that help at all?

        -- zigdon