a.kumaresh has asked for the wisdom of the Perl Monks concerning the following question:

I am new to perl; have good background in C. I am trying to do nested structures. Here is what i am trying to do (in C)

struct child_t { char type[10]; }; struct parent_t { char type[10]; struct * child_t child; };

My try at perl:

use Class::Struct; struct child_t => { type => '$', }; struct parent_t => { type => '$', children => '$', };
Is this the perl way of doing structures?

Replies are listed 'Best First'.
Re: Nested Class::Struct
by NetWallah (Canon) on Aug 28, 2010 at 14:48 UTC
    use strict; use Class::Struct; struct child_t => { type => '$', }; struct parent_t => { type => '$', child => 'child_t', children=>'@', }; #--- For a single child ---- my $Dad = new parent_t(child=> new child_t(type=>"teenager")); print $Dad->child->type() . "\n"; #------ To use Multiple Children --- my $index=0; for (2..6){ $Dad->children($index++, new child_t(type=>"Type $_")); } for (@{ $Dad->children() }){ print "Kid type " . $_->type() . "\n"; }

         Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

      thanks :) that worked. I was trying to use push and friends. like this push @{Dad->children}, child_t_new();Resulted in undefined object method children error.
        Well - that is the more perlish approach to adding elements to the array.
        This works:
        push @{ $Dad->children }, new child_t(type=>"Flower Child");
        This is closer to the syntax you were attempting (also works):
        push @{ $Dad->children }, child_t::new('child_t','type',"Wild Child") +;
        However, as others have pointed out, Class::Struct is a stepping stone into OO perl programming.
        I abandoned it fairly soon after learning the many more powerful constructs in OO perl.

        I'm still learning (after using perl for 8 years), and heading towards Moose (Which is sort of built-in to perl6).

        Update: The second example above is unnatural - here is a better way:

        push @{ $Dad->children }, child_t->new(type=>"Natural Child");

             Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

Re: Nested Class::Struct
by NiJo (Friar) on Aug 28, 2010 at 14:49 UTC
    Structures aren't the standard way of doing object oriented programming in perl. Have a look at  perldoc perlobj.
Re: Nested Class::Struct
by oko1 (Deacon) on Aug 28, 2010 at 15:50 UTC

    Also, just on the off-chance you've missed it, take a look at perldsc. If you're not familiar with Perl data structures, it can be a real wake-up call. :)


    --
    "Language shapes the way we think, and determines what we can think about."
    -- B. L. Whorf
      thank you. I never knew this!
Re: Nested Class::Struct
by Marshall (Canon) on Aug 29, 2010 at 05:40 UTC
    This is a long post, but the question being asked leads to more involved things.

    Glad to see a new "Perler" in the making! Perl data structures are a lot more "free form" than C. In general, although possible to do, you will not see any kind of structure declarations like you would in C. I think the attempt to use Class::Struct is misguided.

    After deciding how you want to represent your data, you just essentially immediately start doing it! Whoa! Rather than get all hypothetical here, I just coded a couple of examples for you (see below for code).

    I don't know why some posters assumed that the OP trying to do some OO thing! In C, defining structures like this is VERY common in function oriented C programming.

    In C you are familiar with the term "pointer", in Perl, you can pretty much equate that concept with "reference". Its not exactly the same at a very low level, but in a practical sense, it is close enough.

    Below in example 1, we have a roster. This roster is represented by an array of anonymous hash references. In C you might use say some kind of linked list or an array of struct. In Perl an array of references to hash provides the same functionality. The use of hash tables will be very common in Perl code - the Perl implementation of this is very efficient.

    The first statement just says that there is an array called roster and it gets initialized to "undefined". There are no "declaration" statements, I just plunge right into growing the roster. Next statement says add a record. Here I decided that there is going to be a parent's name and some number of kid names. The kid_names are represented by an anonymous array of strings. BTW, in Perl an array can contain "mixed types" like integers, strings, floats, etc., but here just strings are used.

    Then next statement gets really complex. This whole idea of an array of hashes got nested! This is an array of hash, where the value of one key in the hash is yet another array of hashes! Once you understand something this complicated, you've covered 99% of what you will normally see in practice.

    I show how to print some things about this structure. $roster[1] is a hash reference. So I can de-reference that thing and say "give me the keys", which here I called "field names". That's what the first print loop does. Note: that this is a question that I can ask about the structure at run time, not something that has to be known at compile time via some struct declaration!

    The 2nd entry in roster $roster[1]{'childern'} is an array of references to hash, actually just like the higher level AoH (Array of Hash). To print the names of the children, I have a loop to get all of the hash references ($href), that the children array contains. This is done by generating each reference to hash, then I deference each hash reference and print the 'name'.

    Of course all this deference this and that can get really complicated. But again Perl is different from C in that you can use Data::Dumper to print out some complicated thing without knowing the details via compile time declarations. This is a REAL butt saver! You will use this often.

    Below although I add two very different types of records to roster, there is nothing that prevents me from doing so. roster is not an array of some pre-defined type of things. I wouldn't do what I did below in real code, but I wanted to show a simple thing and a more complex thing.

    Update: I would like to add that the very strange thing about Perl data structures is that there is nothing that says "how big is this thing?". In C you would have perhaps a NULL pointer in a linked list or some other method like an int representing the number of elements in an array of struct, but in Perl, that is not needed!! Whoa! I regret using an index in the example as that also is an uncommon Perl thing. It is quite possible that you could write your first 5 thousand lines of Perl code and never use an array index or a C style for loop. So I demonstrated a rare thing. But I did it and so it is what it is.

    #!/usr/bin/perl -w use strict; use Data::Dumper; my @roster; push (@roster, {'parentname' => "bob Smith", 'kid_names' => ["little bobby","big bill"], }); push (@roster, { parentname => "mary Jane", childern => [ { name => "little sue", favcolor => "blue" }, { name => "big bertha", favcolor => "green" }, ], }); print "roster field names for 2nd entry:\n"; + foreach my $field (keys %{$roster[1]}) { print " $field\n"; } print "\nthe names of the children for this parent:\n"; foreach my $href( @{$roster[1]{'childern'}} ) { print " $href->{'name'}\n"; } print Dumper \@roster; __END__ Prints: roster field names for 2nd entry: parentname childern the names of the children for this parent: little sue big bertha $VAR1 = [ { 'kid_names' => [ 'little bobby', 'big bill' ], 'parentname' => 'bob Smith' }, { 'parentname' => 'mary Jane', 'childern' => [ { 'favcolor' => 'blue', 'name' => 'little sue' }, { 'favcolor' => 'green', 'name' => 'big bertha' } ] } ];
Re: Nested Class::Struct
by TomDLux (Vicar) on Aug 29, 2010 at 01:53 UTC

    If you want objects, take a look at Moose. It's big and too complicated, but it's useful.

    If you don't want objects, Perl is far more casual about structures than C.

    As Occam said: Entia non sunt multiplicanda praeter necessitatem.