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

Dear Fellow Monks,

I want to create a class that uses a complex data structure, but I am having trouble understanding how I am to access this class data... I want one of my hash keys to point to an array of arrays...

For Example:

package foo; sub new { my ($class) = @_; bless { some_scalar => "blah", another_scalar => "blah", some_array => [], an_array_of_arrays => *?? don't know ??*, },$class; }

How do I declare (and use) a structure like this? I tried something like:

my ($class) = @_; my @array1 = (1,2,3); my @array2 = (4,5,6); my $ref_to_array_1 = \@array1; my $ref_to_array_2 = \@array2; #and then: bless {an_array_of_arrays => $ref_to_array1[$ref_to_array2], some_scalar => "foo-bar", },$class;

But this is really crazy, it doesn't work, and I think it is an improper use of references! Anyway monks, I can't figure out how to go about this, any tips or pointers (no pun intended) would really help...

Replies are listed 'Best First'.
(crazyinsomniac) Re: Complex Data Structures in Object Creation
by crazyinsomniac (Prior) on Jun 24, 2001 at 12:38 UTC
    Oh yee of little sanity, check ye pod before you falleth from grace.. ;-^)

    Check out perlref or perlreftut for help on creating references and 2d arrays. And there's always the Categorized Questions and Answers section.

    to make a two dimensional array (an array of arrays), do something like:

    my @array = (1,2,3); my @2darray = (\@array, \@array, \@array); #or my @3darray = ( [ [11,12,13], [21,22,23], [31,32,33] ] ); print $3darray[0][3][3]; # yields 33
    update: Actually print $3darray[0][2][2]; # yields 33. Just keepin' you on yer toes, zort Masem.

    update:
    Disregard what Zaxo said.

    You don't lose the anonymous hash since it is being returned implicitly (because it is the last statement in sub, and bless returns the reference being blessed).

    However, I do like to return things explicitly, as you never know what'll happen in perl 6 (doesn't really matter if you don't use it, but its good to be as explicit as possible).

    Basically, what I would do is:

    package foo; sub new { my ($class) = shift; my $self = {}; # a ref to an anon hash $self->{some_scalar} = "blah"; $self->{an_array_of_arrays} = [ [01,02], [11,12], [21,22]]; bless ( $self , $class ); return $self; } #so when you do my $new_object = new foo; my $array_ref = $new_object->{an_array_of_arrays}; print $array_ref->[1][1];

     
    ___crazyinsomniac_______________________________________
    Disclaimer: Don't blame. It came from inside the void

    perl -e "$q=$_;map({chr unpack qq;H*;,$_}split(q;;,q*H*));print;$q/$q;"

Re: Complex Data Structures in Object Creation
by Zaxo (Archbishop) on Jun 24, 2001 at 12:38 UTC
    By leaving your data structure anonymous, you lose the means of access to it. The fix is simple:

    package foo; sub new { my $class = shift; # Default initialization my $self = { 'some_scalar' => "", 'another_scalar' => "", 'some_array' => [], 'an_array_of_arrays' => [], # also }; # initialize $self from @_. # you may be calling package functions which expect to shift in a r +ef to data. bless $self, $class; }

    Now methods can use $self to deal with the data.

    Update: crazyinsomniac and chromatic have both objected to this. An instance of foo can provide itself with a name for the ref returned by bless. foo::bar() needs to shift in the instance from its first argument, that's standard. Why ever name something? I was assuming that the real constructor would find named data handy, as in setting up closures as class methods (e.g. accessors ala Class::Struct). If there is an implicit way of doing that on an anonymous ref, I'd enjoy learning it.

    Update2: Added a couple of comments to code. How do you call a package function from the constructor without a named reference? A complex data struct will have special methods for dealing with its components, and some of them will be wanted in new(). In C++ you can't use object methods in a ctor, but perl is different.

    After Compline,
    Zaxo

      Try it.

      What is the scoping of $self in your example? What does bless return? At the end of the subroutine, how many references are there to the anonymous hash?

      It's still an anonymous hash even if it has a named scalar as a referent.

Re: Complex Data Structures in Object Creation
by Anonymous Monk on Jun 24, 2001 at 12:39 UTC
    Ok, building and de-refrencing large data structures often gets to be difficult. for arrays-of-arrays, i use the following :
    bless { some_scalar => "blah", another_scalar => "blah", some_array => [], an_array_of_arrays => [[1,2,3]["a","b","c"]], },$class
    Now, from a design side this would look like :
    $b = $object->{an_array_of_arrays}->[1][1]; # $b has "b"
    This is the anonymous array version. You were close with the ref version, with one change. you can do :
    # old an_array_of_arrays => $ref_to_array1[$ref_to_array2], # new an_array_of_arrays => [$ref_to_array1,$ref_to_array2],
    Hope that helps.