source: trunk/third/perl/pod/perldsc.pod @ 14545

Revision 14545, 24.2 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14544, which included commits to RCS files with non-trunk default branches.
Line 
1=head1 NAME
2
3perldsc - Perl Data Structures Cookbook
4
5=head1 DESCRIPTION
6
7The single feature most sorely lacking in the Perl programming language
8prior to its 5.0 release was complex data structures.  Even without direct
9language support, some valiant programmers did manage to emulate them, but
10it was hard work and not for the faint of heart.  You could occasionally
11get away with the C<$m{$AoA,$b}> notation borrowed from B<awk> in which the
12keys are actually more like a single concatenated string C<"$AoA$b">, but
13traversal and sorting were difficult.  More desperate programmers even
14hacked Perl's internal symbol table directly, a strategy that proved hard
15to develop and maintain--to put it mildly.
16
17The 5.0 release of Perl let us have complex data structures.  You
18may now write something like this and all of a sudden, you'd have a array
19with three dimensions!
20
21    for $x (1 .. 10) {
22        for $y (1 .. 10) {
23            for $z (1 .. 10) {
24                $AoA[$x][$y][$z] =
25                    $x ** $y + $z;
26            }
27        }
28    }
29
30Alas, however simple this may appear, underneath it's a much more
31elaborate construct than meets the eye!
32
33How do you print it out?  Why can't you say just C<print @AoA>?  How do
34you sort it?  How can you pass it to a function or get one of these back
35from a function?  Is is an object?  Can you save it to disk to read
36back later?  How do you access whole rows or columns of that matrix?  Do
37all the values have to be numeric?
38
39As you see, it's quite easy to become confused.  While some small portion
40of the blame for this can be attributed to the reference-based
41implementation, it's really more due to a lack of existing documentation with
42examples designed for the beginner.
43
44This document is meant to be a detailed but understandable treatment of the
45many different sorts of data structures you might want to develop.  It
46should also serve as a cookbook of examples.  That way, when you need to
47create one of these complex data structures, you can just pinch, pilfer, or
48purloin a drop-in example from here.
49
50Let's look at each of these possible constructs in detail.  There are separate
51sections on each of the following:
52
53=over 5
54
55=item * arrays of arrays
56
57=item * hashes of arrays
58
59=item * arrays of hashes
60
61=item * hashes of hashes
62
63=item * more elaborate constructs
64
65=back
66
67But for now, let's look at general issues common to all
68these types of data structures.
69
70=head1 REFERENCES
71
72The most important thing to understand about all data structures in Perl
73-- including multidimensional arrays--is that even though they might
74appear otherwise, Perl C<@ARRAY>s and C<%HASH>es are all internally
75one-dimensional.  They can hold only scalar values (meaning a string,
76number, or a reference).  They cannot directly contain other arrays or
77hashes, but instead contain I<references> to other arrays or hashes.
78
79You can't use a reference to a array or hash in quite the same way that you
80would a real array or hash.  For C or C++ programmers unused to
81distinguishing between arrays and pointers to the same, this can be
82confusing.  If so, just think of it as the difference between a structure
83and a pointer to a structure.
84
85You can (and should) read more about references in the perlref(1) man
86page.  Briefly, references are rather like pointers that know what they
87point to.  (Objects are also a kind of reference, but we won't be needing
88them right away--if ever.)  This means that when you have something which
89looks to you like an access to a two-or-more-dimensional array and/or hash,
90what's really going on is that the base type is
91merely a one-dimensional entity that contains references to the next
92level.  It's just that you can I<use> it as though it were a
93two-dimensional one.  This is actually the way almost all C
94multidimensional arrays work as well.
95
96    $array[7][12]                       # array of arrays
97    $array[7]{string}                   # array of hashes
98    $hash{string}[7]                    # hash of arrays
99    $hash{string}{'another string'}     # hash of hashes
100
101Now, because the top level contains only references, if you try to print
102out your array in with a simple print() function, you'll get something
103that doesn't look very nice, like this:
104
105    @AoA = ( [2, 3], [4, 5, 7], [0] );
106    print $AoA[1][2];
107  7
108    print @AoA;
109  ARRAY(0x83c38)ARRAY(0x8b194)ARRAY(0x8b1d0)
110
111
112That's because Perl doesn't (ever) implicitly dereference your variables.
113If you want to get at the thing a reference is referring to, then you have
114to do this yourself using either prefix typing indicators, like
115C<${$blah}>, C<@{$blah}>, C<@{$blah[$i]}>, or else postfix pointer arrows,
116like C<$a-E<gt>[3]>, C<$h-E<gt>{fred}>, or even C<$ob-E<gt>method()-E<gt>[3]>.
117
118=head1 COMMON MISTAKES
119
120The two most common mistakes made in constructing something like
121an array of arrays is either accidentally counting the number of
122elements or else taking a reference to the same memory location
123repeatedly.  Here's the case where you just get the count instead
124of a nested array:
125
126    for $i (1..10) {
127        @array = somefunc($i);
128        $AoA[$i] = @array;      # WRONG!
129    }
130
131That's just the simple case of assigning an array to a scalar and getting
132its element count.  If that's what you really and truly want, then you
133might do well to consider being a tad more explicit about it, like this:
134
135    for $i (1..10) {
136        @array = somefunc($i);
137        $counts[$i] = scalar @array;
138    }
139
140Here's the case of taking a reference to the same memory location
141again and again:
142
143    for $i (1..10) {
144        @array = somefunc($i);
145        $AoA[$i] = \@array;     # WRONG!
146    }
147
148So, what's the big problem with that?  It looks right, doesn't it?
149After all, I just told you that you need an array of references, so by
150golly, you've made me one!
151
152Unfortunately, while this is true, it's still broken.  All the references
153in @AoA refer to the I<very same place>, and they will therefore all hold
154whatever was last in @array!  It's similar to the problem demonstrated in
155the following C program:
156
157    #include <pwd.h>
158    main() {
159        struct passwd *getpwnam(), *rp, *dp;
160        rp = getpwnam("root");
161        dp = getpwnam("daemon");
162
163        printf("daemon name is %s\nroot name is %s\n",
164                dp->pw_name, rp->pw_name);
165    }
166
167Which will print
168
169    daemon name is daemon
170    root name is daemon
171
172The problem is that both C<rp> and C<dp> are pointers to the same location
173in memory!  In C, you'd have to remember to malloc() yourself some new
174memory.  In Perl, you'll want to use the array constructor C<[]> or the
175hash constructor C<{}> instead.   Here's the right way to do the preceding
176broken code fragments:
177
178    for $i (1..10) {
179        @array = somefunc($i);
180        $AoA[$i] = [ @array ];
181    }
182
183The square brackets make a reference to a new array with a I<copy>
184of what's in @array at the time of the assignment.  This is what
185you want.
186
187Note that this will produce something similar, but it's
188much harder to read:
189
190    for $i (1..10) {
191        @array = 0 .. $i;
192        @{$AoA[$i]} = @array;
193    }
194
195Is it the same?  Well, maybe so--and maybe not.  The subtle difference
196is that when you assign something in square brackets, you know for sure
197it's always a brand new reference with a new I<copy> of the data.
198Something else could be going on in this new case with the C<@{$AoA[$i]}}>
199dereference on the left-hand-side of the assignment.  It all depends on
200whether C<$AoA[$i]> had been undefined to start with, or whether it
201already contained a reference.  If you had already populated @AoA with
202references, as in
203
204    $AoA[3] = \@another_array;
205
206Then the assignment with the indirection on the left-hand-side would
207use the existing reference that was already there:
208
209    @{$AoA[3]} = @array;
210
211Of course, this I<would> have the "interesting" effect of clobbering
212@another_array.  (Have you ever noticed how when a programmer says
213something is "interesting", that rather than meaning "intriguing",
214they're disturbingly more apt to mean that it's "annoying",
215"difficult", or both?  :-)
216
217So just remember always to use the array or hash constructors with C<[]>
218or C<{}>, and you'll be fine, although it's not always optimally
219efficient.
220
221Surprisingly, the following dangerous-looking construct will
222actually work out fine:
223
224    for $i (1..10) {
225        my @array = somefunc($i);
226        $AoA[$i] = \@array;
227    }
228
229That's because my() is more of a run-time statement than it is a
230compile-time declaration I<per se>.  This means that the my() variable is
231remade afresh each time through the loop.  So even though it I<looks> as
232though you stored the same variable reference each time, you actually did
233not!  This is a subtle distinction that can produce more efficient code at
234the risk of misleading all but the most experienced of programmers.  So I
235usually advise against teaching it to beginners.  In fact, except for
236passing arguments to functions, I seldom like to see the gimme-a-reference
237operator (backslash) used much at all in code.  Instead, I advise
238beginners that they (and most of the rest of us) should try to use the
239much more easily understood constructors C<[]> and C<{}> instead of
240relying upon lexical (or dynamic) scoping and hidden reference-counting to
241do the right thing behind the scenes.
242
243In summary:
244
245    $AoA[$i] = [ @array ];      # usually best
246    $AoA[$i] = \@array;         # perilous; just how my() was that array?
247    @{ $AoA[$i] } = @array;     # way too tricky for most programmers
248
249
250=head1 CAVEAT ON PRECEDENCE
251
252Speaking of things like C<@{$AoA[$i]}>, the following are actually the
253same thing:
254
255    $aref->[2][2]       # clear
256    $$aref[2][2]        # confusing
257
258That's because Perl's precedence rules on its five prefix dereferencers
259(which look like someone swearing: C<$ @ * % &>) make them bind more
260tightly than the postfix subscripting brackets or braces!  This will no
261doubt come as a great shock to the C or C++ programmer, who is quite
262accustomed to using C<*a[i]> to mean what's pointed to by the I<i'th>
263element of C<a>.  That is, they first take the subscript, and only then
264dereference the thing at that subscript.  That's fine in C, but this isn't C.
265
266The seemingly equivalent construct in Perl, C<$$aref[$i]> first does
267the deref of $aref, making it take $aref as a reference to an
268array, and then dereference that, and finally tell you the I<i'th> value
269of the array pointed to by $AoA. If you wanted the C notion, you'd have to
270write C<${$AoA[$i]}> to force the C<$AoA[$i]> to get evaluated first
271before the leading C<$> dereferencer.
272
273=head1 WHY YOU SHOULD ALWAYS C<use strict>
274
275If this is starting to sound scarier than it's worth, relax.  Perl has
276some features to help you avoid its most common pitfalls.  The best
277way to avoid getting confused is to start every program like this:
278
279    #!/usr/bin/perl -w
280    use strict;
281
282This way, you'll be forced to declare all your variables with my() and
283also disallow accidental "symbolic dereferencing".  Therefore if you'd done
284this:
285
286    my $aref = [
287        [ "fred", "barney", "pebbles", "bambam", "dino", ],
288        [ "homer", "bart", "marge", "maggie", ],
289        [ "george", "jane", "elroy", "judy", ],
290    ];
291
292    print $aref[2][2];
293
294The compiler would immediately flag that as an error I<at compile time>,
295because you were accidentally accessing C<@aref>, an undeclared
296variable, and it would thereby remind you to write instead:
297
298    print $aref->[2][2]
299
300=head1 DEBUGGING
301
302Before version 5.002, the standard Perl debugger didn't do a very nice job of
303printing out complex data structures.  With 5.002 or above, the
304debugger includes several new features, including command line editing as
305well as the C<x> command to dump out complex data structures.  For
306example, given the assignment to $AoA above, here's the debugger output:
307
308    DB<1> x $AoA
309    $AoA = ARRAY(0x13b5a0)
310       0  ARRAY(0x1f0a24)
311          0  'fred'
312          1  'barney'
313          2  'pebbles'
314          3  'bambam'
315          4  'dino'
316       1  ARRAY(0x13b558)
317          0  'homer'
318          1  'bart'
319          2  'marge'
320          3  'maggie'
321       2  ARRAY(0x13b540)
322          0  'george'
323          1  'jane'
324          2  'elroy'
325          3  'judy'
326
327=head1 CODE EXAMPLES
328
329Presented with little comment (these will get their own manpages someday)
330here are short code examples illustrating access of various
331types of data structures.
332
333=head1 ARRAYS OF ARRAYS
334
335=head2 Declaration of a ARRAY OF ARRAYS
336
337 @AoA = (
338        [ "fred", "barney" ],
339        [ "george", "jane", "elroy" ],
340        [ "homer", "marge", "bart" ],
341      );
342
343=head2 Generation of a ARRAY OF ARRAYS
344
345 # reading from file
346 while ( <> ) {
347     push @AoA, [ split ];
348 }
349
350 # calling a function
351 for $i ( 1 .. 10 ) {
352     $AoA[$i] = [ somefunc($i) ];
353 }
354
355 # using temp vars
356 for $i ( 1 .. 10 ) {
357     @tmp = somefunc($i);
358     $AoA[$i] = [ @tmp ];
359 }
360
361 # add to an existing row
362 push @{ $AoA[0] }, "wilma", "betty";
363
364=head2 Access and Printing of a ARRAY OF ARRAYS
365
366 # one element
367 $AoA[0][0] = "Fred";
368
369 # another element
370 $AoA[1][1] =~ s/(\w)/\u$1/;
371
372 # print the whole thing with refs
373 for $aref ( @AoA ) {
374     print "\t [ @$aref ],\n";
375 }
376
377 # print the whole thing with indices
378 for $i ( 0 .. $#AoA ) {
379     print "\t [ @{$AoA[$i]} ],\n";
380 }
381
382 # print the whole thing one at a time
383 for $i ( 0 .. $#AoA ) {
384     for $j ( 0 .. $#{ $AoA[$i] } ) {
385         print "elt $i $j is $AoA[$i][$j]\n";
386     }
387 }
388
389=head1 HASHES OF ARRAYS
390
391=head2 Declaration of a HASH OF ARRAYS
392
393 %HoA = (
394        flintstones        => [ "fred", "barney" ],
395        jetsons            => [ "george", "jane", "elroy" ],
396        simpsons           => [ "homer", "marge", "bart" ],
397      );
398
399=head2 Generation of a HASH OF ARRAYS
400
401 # reading from file
402 # flintstones: fred barney wilma dino
403 while ( <> ) {
404     next unless s/^(.*?):\s*//;
405     $HoA{$1} = [ split ];
406 }
407
408 # reading from file; more temps
409 # flintstones: fred barney wilma dino
410 while ( $line = <> ) {
411     ($who, $rest) = split /:\s*/, $line, 2;
412     @fields = split ' ', $rest;
413     $HoA{$who} = [ @fields ];
414 }
415
416 # calling a function that returns a list
417 for $group ( "simpsons", "jetsons", "flintstones" ) {
418     $HoA{$group} = [ get_family($group) ];
419 }
420
421 # likewise, but using temps
422 for $group ( "simpsons", "jetsons", "flintstones" ) {
423     @members = get_family($group);
424     $HoA{$group} = [ @members ];
425 }
426
427 # append new members to an existing family
428 push @{ $HoA{"flintstones"} }, "wilma", "betty";
429
430=head2 Access and Printing of a HASH OF ARRAYS
431
432 # one element
433 $HoA{flintstones}[0] = "Fred";
434
435 # another element
436 $HoA{simpsons}[1] =~ s/(\w)/\u$1/;
437
438 # print the whole thing
439 foreach $family ( keys %HoA ) {
440     print "$family: @{ $HoA{$family} }\n"
441 }
442
443 # print the whole thing with indices
444 foreach $family ( keys %HoA ) {
445     print "family: ";
446     foreach $i ( 0 .. $#{ $HoA{$family} } ) {
447         print " $i = $HoA{$family}[$i]";
448     }
449     print "\n";
450 }
451
452 # print the whole thing sorted by number of members
453 foreach $family ( sort { @{$HoA{$b}} <=> @{$HoA{$a}} } keys %HoA ) {
454     print "$family: @{ $HoA{$family} }\n"
455 }
456
457 # print the whole thing sorted by number of members and name
458 foreach $family ( sort {
459                            @{$HoA{$b}} <=> @{$HoA{$a}}
460                                        ||
461                                    $a cmp $b
462            } keys %HoA )
463 {
464     print "$family: ", join(", ", sort @{ $HoA{$family} }), "\n";
465 }
466
467=head1 ARRAYS OF HASHES
468
469=head2 Declaration of a ARRAY OF HASHES
470
471 @AoH = (
472        {
473            Lead     => "fred",
474            Friend   => "barney",
475        },
476        {
477            Lead     => "george",
478            Wife     => "jane",
479            Son      => "elroy",
480        },
481        {
482            Lead     => "homer",
483            Wife     => "marge",
484            Son      => "bart",
485        }
486  );
487
488=head2 Generation of a ARRAY OF HASHES
489
490 # reading from file
491 # format: LEAD=fred FRIEND=barney
492 while ( <> ) {
493     $rec = {};
494     for $field ( split ) {
495         ($key, $value) = split /=/, $field;
496         $rec->{$key} = $value;
497     }
498     push @AoH, $rec;
499 }
500
501
502 # reading from file
503 # format: LEAD=fred FRIEND=barney
504 # no temp
505 while ( <> ) {
506     push @AoH, { split /[\s+=]/ };
507 }
508
509 # calling a function  that returns a key/value pair list, like
510 # "lead","fred","daughter","pebbles"
511 while ( %fields = getnextpairset() ) {
512     push @AoH, { %fields };
513 }
514
515 # likewise, but using no temp vars
516 while (<>) {
517     push @AoH, { parsepairs($_) };
518 }
519
520 # add key/value to an element
521 $AoH[0]{pet} = "dino";
522 $AoH[2]{pet} = "santa's little helper";
523
524=head2 Access and Printing of a ARRAY OF HASHES
525
526 # one element
527 $AoH[0]{lead} = "fred";
528
529 # another element
530 $AoH[1]{lead} =~ s/(\w)/\u$1/;
531
532 # print the whole thing with refs
533 for $href ( @AoH ) {
534     print "{ ";
535     for $role ( keys %$href ) {
536         print "$role=$href->{$role} ";
537     }
538     print "}\n";
539 }
540
541 # print the whole thing with indices
542 for $i ( 0 .. $#AoH ) {
543     print "$i is { ";
544     for $role ( keys %{ $AoH[$i] } ) {
545         print "$role=$AoH[$i]{$role} ";
546     }
547     print "}\n";
548 }
549
550 # print the whole thing one at a time
551 for $i ( 0 .. $#AoH ) {
552     for $role ( keys %{ $AoH[$i] } ) {
553         print "elt $i $role is $AoH[$i]{$role}\n";
554     }
555 }
556
557=head1 HASHES OF HASHES
558
559=head2 Declaration of a HASH OF HASHES
560
561 %HoH = (
562        flintstones => {
563                lead      => "fred",
564                pal       => "barney",
565        },
566        jetsons     => {
567                lead      => "george",
568                wife      => "jane",
569                "his boy" => "elroy",
570        },
571        simpsons    => {
572                lead      => "homer",
573                wife      => "marge",
574                kid       => "bart",
575        },
576 );
577
578=head2 Generation of a HASH OF HASHES
579
580 # reading from file
581 # flintstones: lead=fred pal=barney wife=wilma pet=dino
582 while ( <> ) {
583     next unless s/^(.*?):\s*//;
584     $who = $1;
585     for $field ( split ) {
586         ($key, $value) = split /=/, $field;
587         $HoH{$who}{$key} = $value;
588     }
589
590
591 # reading from file; more temps
592 while ( <> ) {
593     next unless s/^(.*?):\s*//;
594     $who = $1;
595     $rec = {};
596     $HoH{$who} = $rec;
597     for $field ( split ) {
598         ($key, $value) = split /=/, $field;
599         $rec->{$key} = $value;
600     }
601 }
602
603 # calling a function  that returns a key,value hash
604 for $group ( "simpsons", "jetsons", "flintstones" ) {
605     $HoH{$group} = { get_family($group) };
606 }
607
608 # likewise, but using temps
609 for $group ( "simpsons", "jetsons", "flintstones" ) {
610     %members = get_family($group);
611     $HoH{$group} = { %members };
612 }
613
614 # append new members to an existing family
615 %new_folks = (
616     wife => "wilma",
617     pet  => "dino",
618 );
619
620 for $what (keys %new_folks) {
621     $HoH{flintstones}{$what} = $new_folks{$what};
622 }
623
624=head2 Access and Printing of a HASH OF HASHES
625
626 # one element
627 $HoH{flintstones}{wife} = "wilma";
628
629 # another element
630 $HoH{simpsons}{lead} =~ s/(\w)/\u$1/;
631
632 # print the whole thing
633 foreach $family ( keys %HoH ) {
634     print "$family: { ";
635     for $role ( keys %{ $HoH{$family} } ) {
636         print "$role=$HoH{$family}{$role} ";
637     }
638     print "}\n";
639 }
640
641 # print the whole thing  somewhat sorted
642 foreach $family ( sort keys %HoH ) {
643     print "$family: { ";
644     for $role ( sort keys %{ $HoH{$family} } ) {
645         print "$role=$HoH{$family}{$role} ";
646     }
647     print "}\n";
648 }
649
650
651 # print the whole thing sorted by number of members
652 foreach $family ( sort { keys %{$HoH{$b}} <=> keys %{$HoH{$a}} } keys %HoH ) {
653     print "$family: { ";
654     for $role ( sort keys %{ $HoH{$family} } ) {
655         print "$role=$HoH{$family}{$role} ";
656     }
657     print "}\n";
658 }
659
660 # establish a sort order (rank) for each role
661 $i = 0;
662 for ( qw(lead wife son daughter pal pet) ) { $rank{$_} = ++$i }
663
664 # now print the whole thing sorted by number of members
665 foreach $family ( sort { keys %{ $HoH{$b} } <=> keys %{ $HoH{$a} } } keys %HoH ) {
666     print "$family: { ";
667     # and print these according to rank order
668     for $role ( sort { $rank{$a} <=> $rank{$b} }  keys %{ $HoH{$family} } ) {
669         print "$role=$HoH{$family}{$role} ";
670     }
671     print "}\n";
672 }
673
674
675=head1 MORE ELABORATE RECORDS
676
677=head2 Declaration of MORE ELABORATE RECORDS
678
679Here's a sample showing how to create and use a record whose fields are of
680many different sorts:
681
682     $rec = {
683         TEXT      => $string,
684         SEQUENCE  => [ @old_values ],
685         LOOKUP    => { %some_table },
686         THATCODE  => \&some_function,
687         THISCODE  => sub { $_[0] ** $_[1] },
688         HANDLE    => \*STDOUT,
689     };
690
691     print $rec->{TEXT};
692
693     print $rec->{SEQUENCE}[0];
694     $last = pop @ { $rec->{SEQUENCE} };
695
696     print $rec->{LOOKUP}{"key"};
697     ($first_k, $first_v) = each %{ $rec->{LOOKUP} };
698
699     $answer = $rec->{THATCODE}->($arg);
700     $answer = $rec->{THISCODE}->($arg1, $arg2);
701
702     # careful of extra block braces on fh ref
703     print { $rec->{HANDLE} } "a string\n";
704
705     use FileHandle;
706     $rec->{HANDLE}->autoflush(1);
707     $rec->{HANDLE}->print(" a string\n");
708
709=head2 Declaration of a HASH OF COMPLEX RECORDS
710
711     %TV = (
712        flintstones => {
713            series   => "flintstones",
714            nights   => [ qw(monday thursday friday) ],
715            members  => [
716                { name => "fred",    role => "lead", age  => 36, },
717                { name => "wilma",   role => "wife", age  => 31, },
718                { name => "pebbles", role => "kid",  age  =>  4, },
719            ],
720        },
721
722        jetsons     => {
723            series   => "jetsons",
724            nights   => [ qw(wednesday saturday) ],
725            members  => [
726                { name => "george",  role => "lead", age  => 41, },
727                { name => "jane",    role => "wife", age  => 39, },
728                { name => "elroy",   role => "kid",  age  =>  9, },
729            ],
730         },
731
732        simpsons    => {
733            series   => "simpsons",
734            nights   => [ qw(monday) ],
735            members  => [
736                { name => "homer", role => "lead", age  => 34, },
737                { name => "marge", role => "wife", age => 37, },
738                { name => "bart",  role => "kid",  age  =>  11, },
739            ],
740         },
741      );
742
743=head2 Generation of a HASH OF COMPLEX RECORDS
744
745     # reading from file
746     # this is most easily done by having the file itself be
747     # in the raw data format as shown above.  perl is happy
748     # to parse complex data structures if declared as data, so
749     # sometimes it's easiest to do that
750
751     # here's a piece by piece build up
752     $rec = {};
753     $rec->{series} = "flintstones";
754     $rec->{nights} = [ find_days() ];
755
756     @members = ();
757     # assume this file in field=value syntax
758     while (<>) {
759         %fields = split /[\s=]+/;
760         push @members, { %fields };
761     }
762     $rec->{members} = [ @members ];
763
764     # now remember the whole thing
765     $TV{ $rec->{series} } = $rec;
766
767     ###########################################################
768     # now, you might want to make interesting extra fields that
769     # include pointers back into the same data structure so if
770     # change one piece, it changes everywhere, like for example
771     # if you wanted a {kids} field that was a reference
772     # to an array of the kids' records without having duplicate
773     # records and thus update problems.
774     ###########################################################
775     foreach $family (keys %TV) {
776         $rec = $TV{$family}; # temp pointer
777         @kids = ();
778         for $person ( @{ $rec->{members} } ) {
779             if ($person->{role} =~ /kid|son|daughter/) {
780                 push @kids, $person;
781             }
782         }
783         # REMEMBER: $rec and $TV{$family} point to same data!!
784         $rec->{kids} = [ @kids ];
785     }
786
787     # you copied the array, but the array itself contains pointers
788     # to uncopied objects. this means that if you make bart get
789     # older via
790
791     $TV{simpsons}{kids}[0]{age}++;
792
793     # then this would also change in
794     print $TV{simpsons}{members}[2]{age};
795
796     # because $TV{simpsons}{kids}[0] and $TV{simpsons}{members}[2]
797     # both point to the same underlying anonymous hash table
798
799     # print the whole thing
800     foreach $family ( keys %TV ) {
801         print "the $family";
802         print " is on during @{ $TV{$family}{nights} }\n";
803         print "its members are:\n";
804         for $who ( @{ $TV{$family}{members} } ) {
805             print " $who->{name} ($who->{role}), age $who->{age}\n";
806         }
807         print "it turns out that $TV{$family}{lead} has ";
808         print scalar ( @{ $TV{$family}{kids} } ), " kids named ";
809         print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } );
810         print "\n";
811     }
812
813=head1 Database Ties
814
815You cannot easily tie a multilevel data structure (such as a hash of
816hashes) to a dbm file.  The first problem is that all but GDBM and
817Berkeley DB have size limitations, but beyond that, you also have problems
818with how references are to be represented on disk.  One experimental
819module that does partially attempt to address this need is the MLDBM
820module.  Check your nearest CPAN site as described in L<perlmodlib> for
821source code to MLDBM.
822
823=head1 SEE ALSO
824
825perlref(1), perllol(1), perldata(1), perlobj(1)
826
827=head1 AUTHOR
828
829Tom Christiansen <F<tchrist@perl.com>>
830
831Last update:
832Wed Oct 23 04:57:50 MET DST 1996
Note: See TracBrowser for help on using the repository browser.