Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | .\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13 |
2 | .\" | |
3 | .\" Standard preamble: | |
4 | .\" ======================================================================== | |
5 | .de Sh \" Subsection heading | |
6 | .br | |
7 | .if t .Sp | |
8 | .ne 5 | |
9 | .PP | |
10 | \fB\\$1\fR | |
11 | .PP | |
12 | .. | |
13 | .de Sp \" Vertical space (when we can't use .PP) | |
14 | .if t .sp .5v | |
15 | .if n .sp | |
16 | .. | |
17 | .de Vb \" Begin verbatim text | |
18 | .ft CW | |
19 | .nf | |
20 | .ne \\$1 | |
21 | .. | |
22 | .de Ve \" End verbatim text | |
23 | .ft R | |
24 | .fi | |
25 | .. | |
26 | .\" Set up some character translations and predefined strings. \*(-- will | |
27 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left | |
28 | .\" double quote, and \*(R" will give a right double quote. | will give a | |
29 | .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to | |
30 | .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' | |
31 | .\" expand to `' in nroff, nothing in troff, for use with C<>. | |
32 | .tr \(*W-|\(bv\*(Tr | |
33 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' | |
34 | .ie n \{\ | |
35 | . ds -- \(*W- | |
36 | . ds PI pi | |
37 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch | |
38 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch | |
39 | . ds L" "" | |
40 | . ds R" "" | |
41 | . ds C` "" | |
42 | . ds C' "" | |
43 | 'br\} | |
44 | .el\{\ | |
45 | . ds -- \|\(em\| | |
46 | . ds PI \(*p | |
47 | . ds L" `` | |
48 | . ds R" '' | |
49 | 'br\} | |
50 | .\" | |
51 | .\" If the F register is turned on, we'll generate index entries on stderr for | |
52 | .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index | |
53 | .\" entries marked with X<> in POD. Of course, you'll have to process the | |
54 | .\" output yourself in some meaningful fashion. | |
55 | .if \nF \{\ | |
56 | . de IX | |
57 | . tm Index:\\$1\t\\n%\t"\\$2" | |
58 | .. | |
59 | . nr % 0 | |
60 | . rr F | |
61 | .\} | |
62 | .\" | |
63 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes | |
64 | .\" way too many mistakes in technical documents. | |
65 | .hy 0 | |
66 | .if n .na | |
67 | .\" | |
68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). | |
69 | .\" Fear. Run. Save yourself. No user-serviceable parts. | |
70 | . \" fudge factors for nroff and troff | |
71 | .if n \{\ | |
72 | . ds #H 0 | |
73 | . ds #V .8m | |
74 | . ds #F .3m | |
75 | . ds #[ \f1 | |
76 | . ds #] \fP | |
77 | .\} | |
78 | .if t \{\ | |
79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) | |
80 | . ds #V .6m | |
81 | . ds #F 0 | |
82 | . ds #[ \& | |
83 | . ds #] \& | |
84 | .\} | |
85 | . \" simple accents for nroff and troff | |
86 | .if n \{\ | |
87 | . ds ' \& | |
88 | . ds ` \& | |
89 | . ds ^ \& | |
90 | . ds , \& | |
91 | . ds ~ ~ | |
92 | . ds / | |
93 | .\} | |
94 | .if t \{\ | |
95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" | |
96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' | |
97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' | |
98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' | |
99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' | |
100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' | |
101 | .\} | |
102 | . \" troff and (daisy-wheel) nroff accents | |
103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' | |
104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' | |
105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] | |
106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' | |
107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' | |
108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] | |
109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] | |
110 | .ds ae a\h'-(\w'a'u*4/10)'e | |
111 | .ds Ae A\h'-(\w'A'u*4/10)'E | |
112 | . \" corrections for vroff | |
113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' | |
114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' | |
115 | . \" for low resolution devices (crt and lpr) | |
116 | .if \n(.H>23 .if \n(.V>19 \ | |
117 | \{\ | |
118 | . ds : e | |
119 | . ds 8 ss | |
120 | . ds o a | |
121 | . ds d- d\h'-1'\(ga | |
122 | . ds D- D\h'-1'\(hy | |
123 | . ds th \o'bp' | |
124 | . ds Th \o'LP' | |
125 | . ds ae ae | |
126 | . ds Ae AE | |
127 | .\} | |
128 | .rm #[ #] #H #V #F C | |
129 | .\" ======================================================================== | |
130 | .\" | |
131 | .IX Title "PERLDSC 1" | |
132 | .TH PERLDSC 1 "2002-06-08" "perl v5.8.0" "Perl Programmers Reference Guide" | |
133 | .SH "NAME" | |
134 | perldsc \- Perl Data Structures Cookbook | |
135 | .SH "DESCRIPTION" | |
136 | .IX Header "DESCRIPTION" | |
137 | The single feature most sorely lacking in the Perl programming language | |
138 | prior to its 5.0 release was complex data structures. Even without direct | |
139 | language support, some valiant programmers did manage to emulate them, but | |
140 | it was hard work and not for the faint of heart. You could occasionally | |
141 | get away with the \f(CW$m{$AoA,$b}\fR notation borrowed from \fBawk\fR in which the | |
142 | keys are actually more like a single concatenated string \f(CW"$AoA$b"\fR, but | |
143 | traversal and sorting were difficult. More desperate programmers even | |
144 | hacked Perl's internal symbol table directly, a strategy that proved hard | |
145 | to develop and maintain\*(--to put it mildly. | |
146 | .PP | |
147 | The 5.0 release of Perl let us have complex data structures. You | |
148 | may now write something like this and all of a sudden, you'd have an array | |
149 | with three dimensions! | |
150 | .PP | |
151 | .Vb 8 | |
152 | \& for $x (1 .. 10) { | |
153 | \& for $y (1 .. 10) { | |
154 | \& for $z (1 .. 10) { | |
155 | \& $AoA[$x][$y][$z] = | |
156 | \& $x ** $y + $z; | |
157 | \& } | |
158 | \& } | |
159 | \& } | |
160 | .Ve | |
161 | .PP | |
162 | Alas, however simple this may appear, underneath it's a much more | |
163 | elaborate construct than meets the eye! | |
164 | .PP | |
165 | How do you print it out? Why can't you say just \f(CW\*(C`print @AoA\*(C'\fR? How do | |
166 | you sort it? How can you pass it to a function or get one of these back | |
167 | from a function? Is it an object? Can you save it to disk to read | |
168 | back later? How do you access whole rows or columns of that matrix? Do | |
169 | all the values have to be numeric? | |
170 | .PP | |
171 | As you see, it's quite easy to become confused. While some small portion | |
172 | of the blame for this can be attributed to the reference-based | |
173 | implementation, it's really more due to a lack of existing documentation with | |
174 | examples designed for the beginner. | |
175 | .PP | |
176 | This document is meant to be a detailed but understandable treatment of the | |
177 | many different sorts of data structures you might want to develop. It | |
178 | should also serve as a cookbook of examples. That way, when you need to | |
179 | create one of these complex data structures, you can just pinch, pilfer, or | |
180 | purloin a drop-in example from here. | |
181 | .PP | |
182 | Let's look at each of these possible constructs in detail. There are separate | |
183 | sections on each of the following: | |
184 | .IP "\(bu arrays of arrays" 5 | |
185 | .IX Item "arrays of arrays" | |
186 | .PD 0 | |
187 | .IP "\(bu hashes of arrays" 5 | |
188 | .IX Item "hashes of arrays" | |
189 | .IP "\(bu arrays of hashes" 5 | |
190 | .IX Item "arrays of hashes" | |
191 | .IP "\(bu hashes of hashes" 5 | |
192 | .IX Item "hashes of hashes" | |
193 | .IP "\(bu more elaborate constructs" 5 | |
194 | .IX Item "more elaborate constructs" | |
195 | .PD | |
196 | .PP | |
197 | But for now, let's look at general issues common to all | |
198 | these types of data structures. | |
199 | .SH "REFERENCES" | |
200 | .IX Header "REFERENCES" | |
201 | The most important thing to understand about all data structures in Perl | |
202 | \&\*(-- including multidimensional arrays\*(--is that even though they might | |
203 | appear otherwise, Perl \f(CW@ARRAY\fRs and \f(CW%HASH\fRes are all internally | |
204 | one\-dimensional. They can hold only scalar values (meaning a string, | |
205 | number, or a reference). They cannot directly contain other arrays or | |
206 | hashes, but instead contain \fIreferences\fR to other arrays or hashes. | |
207 | .PP | |
208 | You can't use a reference to an array or hash in quite the same way that you | |
209 | would a real array or hash. For C or \*(C+ programmers unused to | |
210 | distinguishing between arrays and pointers to the same, this can be | |
211 | confusing. If so, just think of it as the difference between a structure | |
212 | and a pointer to a structure. | |
213 | .PP | |
214 | You can (and should) read more about references in the \fIperlref\fR\|(1) man | |
215 | page. Briefly, references are rather like pointers that know what they | |
216 | point to. (Objects are also a kind of reference, but we won't be needing | |
217 | them right away\*(--if ever.) This means that when you have something which | |
218 | looks to you like an access to a two-or-more-dimensional array and/or hash, | |
219 | what's really going on is that the base type is | |
220 | merely a one-dimensional entity that contains references to the next | |
221 | level. It's just that you can \fIuse\fR it as though it were a | |
222 | two-dimensional one. This is actually the way almost all C | |
223 | multidimensional arrays work as well. | |
224 | .PP | |
225 | .Vb 4 | |
226 | \& $array[7][12] # array of arrays | |
227 | \& $array[7]{string} # array of hashes | |
228 | \& $hash{string}[7] # hash of arrays | |
229 | \& $hash{string}{'another string'} # hash of hashes | |
230 | .Ve | |
231 | .PP | |
232 | Now, because the top level contains only references, if you try to print | |
233 | out your array in with a simple \fIprint()\fR function, you'll get something | |
234 | that doesn't look very nice, like this: | |
235 | .PP | |
236 | .Vb 5 | |
237 | \& @AoA = ( [2, 3], [4, 5, 7], [0] ); | |
238 | \& print $AoA[1][2]; | |
239 | \& 7 | |
240 | \& print @AoA; | |
241 | \& ARRAY(0x83c38)ARRAY(0x8b194)ARRAY(0x8b1d0) | |
242 | .Ve | |
243 | .PP | |
244 | That's because Perl doesn't (ever) implicitly dereference your variables. | |
245 | If you want to get at the thing a reference is referring to, then you have | |
246 | to do this yourself using either prefix typing indicators, like | |
247 | \&\f(CW\*(C`${$blah}\*(C'\fR, \f(CW\*(C`@{$blah}\*(C'\fR, \f(CW\*(C`@{$blah[$i]}\*(C'\fR, or else postfix pointer arrows, | |
248 | like \f(CW\*(C`$a\->[3]\*(C'\fR, \f(CW\*(C`$h\->{fred}\*(C'\fR, or even \f(CW\*(C`$ob\->method()\->[3]\*(C'\fR. | |
249 | .SH "COMMON MISTAKES" | |
250 | .IX Header "COMMON MISTAKES" | |
251 | The two most common mistakes made in constructing something like | |
252 | an array of arrays is either accidentally counting the number of | |
253 | elements or else taking a reference to the same memory location | |
254 | repeatedly. Here's the case where you just get the count instead | |
255 | of a nested array: | |
256 | .PP | |
257 | .Vb 4 | |
258 | \& for $i (1..10) { | |
259 | \& @array = somefunc($i); | |
260 | \& $AoA[$i] = @array; # WRONG! | |
261 | \& } | |
262 | .Ve | |
263 | .PP | |
264 | That's just the simple case of assigning an array to a scalar and getting | |
265 | its element count. If that's what you really and truly want, then you | |
266 | might do well to consider being a tad more explicit about it, like this: | |
267 | .PP | |
268 | .Vb 4 | |
269 | \& for $i (1..10) { | |
270 | \& @array = somefunc($i); | |
271 | \& $counts[$i] = scalar @array; | |
272 | \& } | |
273 | .Ve | |
274 | .PP | |
275 | Here's the case of taking a reference to the same memory location | |
276 | again and again: | |
277 | .PP | |
278 | .Vb 4 | |
279 | \& for $i (1..10) { | |
280 | \& @array = somefunc($i); | |
281 | \& $AoA[$i] = \e@array; # WRONG! | |
282 | \& } | |
283 | .Ve | |
284 | .PP | |
285 | So, what's the big problem with that? It looks right, doesn't it? | |
286 | After all, I just told you that you need an array of references, so by | |
287 | golly, you've made me one! | |
288 | .PP | |
289 | Unfortunately, while this is true, it's still broken. All the references | |
290 | in \f(CW@AoA\fR refer to the \fIvery same place\fR, and they will therefore all hold | |
291 | whatever was last in \f(CW@array\fR! It's similar to the problem demonstrated in | |
292 | the following C program: | |
293 | .PP | |
294 | .Vb 5 | |
295 | \& #include <pwd.h> | |
296 | \& main() { | |
297 | \& struct passwd *getpwnam(), *rp, *dp; | |
298 | \& rp = getpwnam("root"); | |
299 | \& dp = getpwnam("daemon"); | |
300 | .Ve | |
301 | .PP | |
302 | .Vb 3 | |
303 | \& printf("daemon name is %s\enroot name is %s\en", | |
304 | \& dp->pw_name, rp->pw_name); | |
305 | \& } | |
306 | .Ve | |
307 | .PP | |
308 | Which will print | |
309 | .PP | |
310 | .Vb 2 | |
311 | \& daemon name is daemon | |
312 | \& root name is daemon | |
313 | .Ve | |
314 | .PP | |
315 | The problem is that both \f(CW\*(C`rp\*(C'\fR and \f(CW\*(C`dp\*(C'\fR are pointers to the same location | |
316 | in memory! In C, you'd have to remember to \fImalloc()\fR yourself some new | |
317 | memory. In Perl, you'll want to use the array constructor \f(CW\*(C`[]\*(C'\fR or the | |
318 | hash constructor \f(CW\*(C`{}\*(C'\fR instead. Here's the right way to do the preceding | |
319 | broken code fragments: | |
320 | .PP | |
321 | .Vb 4 | |
322 | \& for $i (1..10) { | |
323 | \& @array = somefunc($i); | |
324 | \& $AoA[$i] = [ @array ]; | |
325 | \& } | |
326 | .Ve | |
327 | .PP | |
328 | The square brackets make a reference to a new array with a \fIcopy\fR | |
329 | of what's in \f(CW@array\fR at the time of the assignment. This is what | |
330 | you want. | |
331 | .PP | |
332 | Note that this will produce something similar, but it's | |
333 | much harder to read: | |
334 | .PP | |
335 | .Vb 4 | |
336 | \& for $i (1..10) { | |
337 | \& @array = 0 .. $i; | |
338 | \& @{$AoA[$i]} = @array; | |
339 | \& } | |
340 | .Ve | |
341 | .PP | |
342 | Is it the same? Well, maybe so\*(--and maybe not. The subtle difference | |
343 | is that when you assign something in square brackets, you know for sure | |
344 | it's always a brand new reference with a new \fIcopy\fR of the data. | |
345 | Something else could be going on in this new case with the \f(CW\*(C`@{$AoA[$i]}}\*(C'\fR | |
346 | dereference on the left-hand-side of the assignment. It all depends on | |
347 | whether \f(CW$AoA[$i]\fR had been undefined to start with, or whether it | |
348 | already contained a reference. If you had already populated \f(CW@AoA\fR with | |
349 | references, as in | |
350 | .PP | |
351 | .Vb 1 | |
352 | \& $AoA[3] = \e@another_array; | |
353 | .Ve | |
354 | .PP | |
355 | Then the assignment with the indirection on the left-hand-side would | |
356 | use the existing reference that was already there: | |
357 | .PP | |
358 | .Vb 1 | |
359 | \& @{$AoA[3]} = @array; | |
360 | .Ve | |
361 | .PP | |
362 | Of course, this \fIwould\fR have the \*(L"interesting\*(R" effect of clobbering | |
363 | \&\f(CW@another_array\fR. (Have you ever noticed how when a programmer says | |
364 | something is \*(L"interesting\*(R", that rather than meaning \*(L"intriguing\*(R", | |
365 | they're disturbingly more apt to mean that it's \*(L"annoying\*(R", | |
366 | \&\*(L"difficult\*(R", or both? :\-) | |
367 | .PP | |
368 | So just remember always to use the array or hash constructors with \f(CW\*(C`[]\*(C'\fR | |
369 | or \f(CW\*(C`{}\*(C'\fR, and you'll be fine, although it's not always optimally | |
370 | efficient. | |
371 | .PP | |
372 | Surprisingly, the following dangerous-looking construct will | |
373 | actually work out fine: | |
374 | .PP | |
375 | .Vb 4 | |
376 | \& for $i (1..10) { | |
377 | \& my @array = somefunc($i); | |
378 | \& $AoA[$i] = \e@array; | |
379 | \& } | |
380 | .Ve | |
381 | .PP | |
382 | That's because \fImy()\fR is more of a run-time statement than it is a | |
383 | compile-time declaration \fIper se\fR. This means that the \fImy()\fR variable is | |
384 | remade afresh each time through the loop. So even though it \fIlooks\fR as | |
385 | though you stored the same variable reference each time, you actually did | |
386 | not! This is a subtle distinction that can produce more efficient code at | |
387 | the risk of misleading all but the most experienced of programmers. So I | |
388 | usually advise against teaching it to beginners. In fact, except for | |
389 | passing arguments to functions, I seldom like to see the gimme-a-reference | |
390 | operator (backslash) used much at all in code. Instead, I advise | |
391 | beginners that they (and most of the rest of us) should try to use the | |
392 | much more easily understood constructors \f(CW\*(C`[]\*(C'\fR and \f(CW\*(C`{}\*(C'\fR instead of | |
393 | relying upon lexical (or dynamic) scoping and hidden reference-counting to | |
394 | do the right thing behind the scenes. | |
395 | .PP | |
396 | In summary: | |
397 | .PP | |
398 | .Vb 3 | |
399 | \& $AoA[$i] = [ @array ]; # usually best | |
400 | \& $AoA[$i] = \e@array; # perilous; just how my() was that array? | |
401 | \& @{ $AoA[$i] } = @array; # way too tricky for most programmers | |
402 | .Ve | |
403 | .SH "CAVEAT ON PRECEDENCE" | |
404 | .IX Header "CAVEAT ON PRECEDENCE" | |
405 | Speaking of things like \f(CW\*(C`@{$AoA[$i]}\*(C'\fR, the following are actually the | |
406 | same thing: | |
407 | .PP | |
408 | .Vb 2 | |
409 | \& $aref->[2][2] # clear | |
410 | \& $$aref[2][2] # confusing | |
411 | .Ve | |
412 | .PP | |
413 | That's because Perl's precedence rules on its five prefix dereferencers | |
414 | (which look like someone swearing: \f(CW\*(C`$ @ * % &\*(C'\fR) make them bind more | |
415 | tightly than the postfix subscripting brackets or braces! This will no | |
416 | doubt come as a great shock to the C or \*(C+ programmer, who is quite | |
417 | accustomed to using \f(CW*a[i]\fR to mean what's pointed to by the \fIi'th\fR | |
418 | element of \f(CW\*(C`a\*(C'\fR. That is, they first take the subscript, and only then | |
419 | dereference the thing at that subscript. That's fine in C, but this isn't C. | |
420 | .PP | |
421 | The seemingly equivalent construct in Perl, \f(CW$$aref[$i]\fR first does | |
422 | the deref of \f(CW$aref\fR, making it take \f(CW$aref\fR as a reference to an | |
423 | array, and then dereference that, and finally tell you the \fIi'th\fR value | |
424 | of the array pointed to by \f(CW$AoA\fR. If you wanted the C notion, you'd have to | |
425 | write \f(CW\*(C`${$AoA[$i]}\*(C'\fR to force the \f(CW$AoA[$i]\fR to get evaluated first | |
426 | before the leading \f(CW\*(C`$\*(C'\fR dereferencer. | |
427 | .ie n .SH "WHY YOU SHOULD ALWAYS ""use strict""" | |
428 | .el .SH "WHY YOU SHOULD ALWAYS \f(CWuse strict\fP" | |
429 | .IX Header "WHY YOU SHOULD ALWAYS use strict" | |
430 | If this is starting to sound scarier than it's worth, relax. Perl has | |
431 | some features to help you avoid its most common pitfalls. The best | |
432 | way to avoid getting confused is to start every program like this: | |
433 | .PP | |
434 | .Vb 2 | |
435 | \& #!/usr/bin/perl -w | |
436 | \& use strict; | |
437 | .Ve | |
438 | .PP | |
439 | This way, you'll be forced to declare all your variables with \fImy()\fR and | |
440 | also disallow accidental \*(L"symbolic dereferencing\*(R". Therefore if you'd done | |
441 | this: | |
442 | .PP | |
443 | .Vb 5 | |
444 | \& my $aref = [ | |
445 | \& [ "fred", "barney", "pebbles", "bambam", "dino", ], | |
446 | \& [ "homer", "bart", "marge", "maggie", ], | |
447 | \& [ "george", "jane", "elroy", "judy", ], | |
448 | \& ]; | |
449 | .Ve | |
450 | .PP | |
451 | .Vb 1 | |
452 | \& print $aref[2][2]; | |
453 | .Ve | |
454 | .PP | |
455 | The compiler would immediately flag that as an error \fIat compile time\fR, | |
456 | because you were accidentally accessing \f(CW@aref\fR, an undeclared | |
457 | variable, and it would thereby remind you to write instead: | |
458 | .PP | |
459 | .Vb 1 | |
460 | \& print $aref->[2][2] | |
461 | .Ve | |
462 | .SH "DEBUGGING" | |
463 | .IX Header "DEBUGGING" | |
464 | Before version 5.002, the standard Perl debugger didn't do a very nice job of | |
465 | printing out complex data structures. With 5.002 or above, the | |
466 | debugger includes several new features, including command line editing as | |
467 | well as the \f(CW\*(C`x\*(C'\fR command to dump out complex data structures. For | |
468 | example, given the assignment to \f(CW$AoA\fR above, here's the debugger output: | |
469 | .PP | |
470 | .Vb 18 | |
471 | \& DB<1> x $AoA | |
472 | \& $AoA = ARRAY(0x13b5a0) | |
473 | \& 0 ARRAY(0x1f0a24) | |
474 | \& 0 'fred' | |
475 | \& 1 'barney' | |
476 | \& 2 'pebbles' | |
477 | \& 3 'bambam' | |
478 | \& 4 'dino' | |
479 | \& 1 ARRAY(0x13b558) | |
480 | \& 0 'homer' | |
481 | \& 1 'bart' | |
482 | \& 2 'marge' | |
483 | \& 3 'maggie' | |
484 | \& 2 ARRAY(0x13b540) | |
485 | \& 0 'george' | |
486 | \& 1 'jane' | |
487 | \& 2 'elroy' | |
488 | \& 3 'judy' | |
489 | .Ve | |
490 | .SH "CODE EXAMPLES" | |
491 | .IX Header "CODE EXAMPLES" | |
492 | Presented with little comment (these will get their own manpages someday) | |
493 | here are short code examples illustrating access of various | |
494 | types of data structures. | |
495 | .SH "ARRAYS OF ARRAYS" | |
496 | .IX Header "ARRAYS OF ARRAYS" | |
497 | .Sh "Declaration of an \s-1ARRAY\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
498 | .IX Subsection "Declaration of an ARRAY OF ARRAYS" | |
499 | .Vb 5 | |
500 | \& @AoA = ( | |
501 | \& [ "fred", "barney" ], | |
502 | \& [ "george", "jane", "elroy" ], | |
503 | \& [ "homer", "marge", "bart" ], | |
504 | \& ); | |
505 | .Ve | |
506 | .Sh "Generation of an \s-1ARRAY\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
507 | .IX Subsection "Generation of an ARRAY OF ARRAYS" | |
508 | .Vb 4 | |
509 | \& # reading from file | |
510 | \& while ( <> ) { | |
511 | \& push @AoA, [ split ]; | |
512 | \& } | |
513 | .Ve | |
514 | .PP | |
515 | .Vb 4 | |
516 | \& # calling a function | |
517 | \& for $i ( 1 .. 10 ) { | |
518 | \& $AoA[$i] = [ somefunc($i) ]; | |
519 | \& } | |
520 | .Ve | |
521 | .PP | |
522 | .Vb 5 | |
523 | \& # using temp vars | |
524 | \& for $i ( 1 .. 10 ) { | |
525 | \& @tmp = somefunc($i); | |
526 | \& $AoA[$i] = [ @tmp ]; | |
527 | \& } | |
528 | .Ve | |
529 | .PP | |
530 | .Vb 2 | |
531 | \& # add to an existing row | |
532 | \& push @{ $AoA[0] }, "wilma", "betty"; | |
533 | .Ve | |
534 | .Sh "Access and Printing of an \s-1ARRAY\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
535 | .IX Subsection "Access and Printing of an ARRAY OF ARRAYS" | |
536 | .Vb 2 | |
537 | \& # one element | |
538 | \& $AoA[0][0] = "Fred"; | |
539 | .Ve | |
540 | .PP | |
541 | .Vb 2 | |
542 | \& # another element | |
543 | \& $AoA[1][1] =~ s/(\ew)/\eu$1/; | |
544 | .Ve | |
545 | .PP | |
546 | .Vb 4 | |
547 | \& # print the whole thing with refs | |
548 | \& for $aref ( @AoA ) { | |
549 | \& print "\et [ @$aref ],\en"; | |
550 | \& } | |
551 | .Ve | |
552 | .PP | |
553 | .Vb 4 | |
554 | \& # print the whole thing with indices | |
555 | \& for $i ( 0 .. $#AoA ) { | |
556 | \& print "\et [ @{$AoA[$i]} ],\en"; | |
557 | \& } | |
558 | .Ve | |
559 | .PP | |
560 | .Vb 6 | |
561 | \& # print the whole thing one at a time | |
562 | \& for $i ( 0 .. $#AoA ) { | |
563 | \& for $j ( 0 .. $#{ $AoA[$i] } ) { | |
564 | \& print "elt $i $j is $AoA[$i][$j]\en"; | |
565 | \& } | |
566 | \& } | |
567 | .Ve | |
568 | .SH "HASHES OF ARRAYS" | |
569 | .IX Header "HASHES OF ARRAYS" | |
570 | .Sh "Declaration of a \s-1HASH\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
571 | .IX Subsection "Declaration of a HASH OF ARRAYS" | |
572 | .Vb 5 | |
573 | \& %HoA = ( | |
574 | \& flintstones => [ "fred", "barney" ], | |
575 | \& jetsons => [ "george", "jane", "elroy" ], | |
576 | \& simpsons => [ "homer", "marge", "bart" ], | |
577 | \& ); | |
578 | .Ve | |
579 | .Sh "Generation of a \s-1HASH\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
580 | .IX Subsection "Generation of a HASH OF ARRAYS" | |
581 | .Vb 6 | |
582 | \& # reading from file | |
583 | \& # flintstones: fred barney wilma dino | |
584 | \& while ( <> ) { | |
585 | \& next unless s/^(.*?):\es*//; | |
586 | \& $HoA{$1} = [ split ]; | |
587 | \& } | |
588 | .Ve | |
589 | .PP | |
590 | .Vb 7 | |
591 | \& # reading from file; more temps | |
592 | \& # flintstones: fred barney wilma dino | |
593 | \& while ( $line = <> ) { | |
594 | \& ($who, $rest) = split /:\es*/, $line, 2; | |
595 | \& @fields = split ' ', $rest; | |
596 | \& $HoA{$who} = [ @fields ]; | |
597 | \& } | |
598 | .Ve | |
599 | .PP | |
600 | .Vb 4 | |
601 | \& # calling a function that returns a list | |
602 | \& for $group ( "simpsons", "jetsons", "flintstones" ) { | |
603 | \& $HoA{$group} = [ get_family($group) ]; | |
604 | \& } | |
605 | .Ve | |
606 | .PP | |
607 | .Vb 5 | |
608 | \& # likewise, but using temps | |
609 | \& for $group ( "simpsons", "jetsons", "flintstones" ) { | |
610 | \& @members = get_family($group); | |
611 | \& $HoA{$group} = [ @members ]; | |
612 | \& } | |
613 | .Ve | |
614 | .PP | |
615 | .Vb 2 | |
616 | \& # append new members to an existing family | |
617 | \& push @{ $HoA{"flintstones"} }, "wilma", "betty"; | |
618 | .Ve | |
619 | .Sh "Access and Printing of a \s-1HASH\s0 \s-1OF\s0 \s-1ARRAYS\s0" | |
620 | .IX Subsection "Access and Printing of a HASH OF ARRAYS" | |
621 | .Vb 2 | |
622 | \& # one element | |
623 | \& $HoA{flintstones}[0] = "Fred"; | |
624 | .Ve | |
625 | .PP | |
626 | .Vb 2 | |
627 | \& # another element | |
628 | \& $HoA{simpsons}[1] =~ s/(\ew)/\eu$1/; | |
629 | .Ve | |
630 | .PP | |
631 | .Vb 4 | |
632 | \& # print the whole thing | |
633 | \& foreach $family ( keys %HoA ) { | |
634 | \& print "$family: @{ $HoA{$family} }\en" | |
635 | \& } | |
636 | .Ve | |
637 | .PP | |
638 | .Vb 8 | |
639 | \& # print the whole thing with indices | |
640 | \& foreach $family ( keys %HoA ) { | |
641 | \& print "family: "; | |
642 | \& foreach $i ( 0 .. $#{ $HoA{$family} } ) { | |
643 | \& print " $i = $HoA{$family}[$i]"; | |
644 | \& } | |
645 | \& print "\en"; | |
646 | \& } | |
647 | .Ve | |
648 | .PP | |
649 | .Vb 4 | |
650 | \& # print the whole thing sorted by number of members | |
651 | \& foreach $family ( sort { @{$HoA{$b}} <=> @{$HoA{$a}} } keys %HoA ) { | |
652 | \& print "$family: @{ $HoA{$family} }\en" | |
653 | \& } | |
654 | .Ve | |
655 | .PP | |
656 | .Vb 9 | |
657 | \& # print the whole thing sorted by number of members and name | |
658 | \& foreach $family ( sort { | |
659 | \& @{$HoA{$b}} <=> @{$HoA{$a}} | |
660 | \& || | |
661 | \& $a cmp $b | |
662 | \& } keys %HoA ) | |
663 | \& { | |
664 | \& print "$family: ", join(", ", sort @{ $HoA{$family} }), "\en"; | |
665 | \& } | |
666 | .Ve | |
667 | .SH "ARRAYS OF HASHES" | |
668 | .IX Header "ARRAYS OF HASHES" | |
669 | .Sh "Declaration of an \s-1ARRAY\s0 \s-1OF\s0 \s-1HASHES\s0" | |
670 | .IX Subsection "Declaration of an ARRAY OF HASHES" | |
671 | .Vb 16 | |
672 | \& @AoH = ( | |
673 | \& { | |
674 | \& Lead => "fred", | |
675 | \& Friend => "barney", | |
676 | \& }, | |
677 | \& { | |
678 | \& Lead => "george", | |
679 | \& Wife => "jane", | |
680 | \& Son => "elroy", | |
681 | \& }, | |
682 | \& { | |
683 | \& Lead => "homer", | |
684 | \& Wife => "marge", | |
685 | \& Son => "bart", | |
686 | \& } | |
687 | \& ); | |
688 | .Ve | |
689 | .Sh "Generation of an \s-1ARRAY\s0 \s-1OF\s0 \s-1HASHES\s0" | |
690 | .IX Subsection "Generation of an ARRAY OF HASHES" | |
691 | .Vb 10 | |
692 | \& # reading from file | |
693 | \& # format: LEAD=fred FRIEND=barney | |
694 | \& while ( <> ) { | |
695 | \& $rec = {}; | |
696 | \& for $field ( split ) { | |
697 | \& ($key, $value) = split /=/, $field; | |
698 | \& $rec->{$key} = $value; | |
699 | \& } | |
700 | \& push @AoH, $rec; | |
701 | \& } | |
702 | .Ve | |
703 | .PP | |
704 | .Vb 6 | |
705 | \& # reading from file | |
706 | \& # format: LEAD=fred FRIEND=barney | |
707 | \& # no temp | |
708 | \& while ( <> ) { | |
709 | \& push @AoH, { split /[\es+=]/ }; | |
710 | \& } | |
711 | .Ve | |
712 | .PP | |
713 | .Vb 5 | |
714 | \& # calling a function that returns a key/value pair list, like | |
715 | \& # "lead","fred","daughter","pebbles" | |
716 | \& while ( %fields = getnextpairset() ) { | |
717 | \& push @AoH, { %fields }; | |
718 | \& } | |
719 | .Ve | |
720 | .PP | |
721 | .Vb 4 | |
722 | \& # likewise, but using no temp vars | |
723 | \& while (<>) { | |
724 | \& push @AoH, { parsepairs($_) }; | |
725 | \& } | |
726 | .Ve | |
727 | .PP | |
728 | .Vb 3 | |
729 | \& # add key/value to an element | |
730 | \& $AoH[0]{pet} = "dino"; | |
731 | \& $AoH[2]{pet} = "santa's little helper"; | |
732 | .Ve | |
733 | .Sh "Access and Printing of an \s-1ARRAY\s0 \s-1OF\s0 \s-1HASHES\s0" | |
734 | .IX Subsection "Access and Printing of an ARRAY OF HASHES" | |
735 | .Vb 2 | |
736 | \& # one element | |
737 | \& $AoH[0]{lead} = "fred"; | |
738 | .Ve | |
739 | .PP | |
740 | .Vb 2 | |
741 | \& # another element | |
742 | \& $AoH[1]{lead} =~ s/(\ew)/\eu$1/; | |
743 | .Ve | |
744 | .PP | |
745 | .Vb 8 | |
746 | \& # print the whole thing with refs | |
747 | \& for $href ( @AoH ) { | |
748 | \& print "{ "; | |
749 | \& for $role ( keys %$href ) { | |
750 | \& print "$role=$href->{$role} "; | |
751 | \& } | |
752 | \& print "}\en"; | |
753 | \& } | |
754 | .Ve | |
755 | .PP | |
756 | .Vb 8 | |
757 | \& # print the whole thing with indices | |
758 | \& for $i ( 0 .. $#AoH ) { | |
759 | \& print "$i is { "; | |
760 | \& for $role ( keys %{ $AoH[$i] } ) { | |
761 | \& print "$role=$AoH[$i]{$role} "; | |
762 | \& } | |
763 | \& print "}\en"; | |
764 | \& } | |
765 | .Ve | |
766 | .PP | |
767 | .Vb 6 | |
768 | \& # print the whole thing one at a time | |
769 | \& for $i ( 0 .. $#AoH ) { | |
770 | \& for $role ( keys %{ $AoH[$i] } ) { | |
771 | \& print "elt $i $role is $AoH[$i]{$role}\en"; | |
772 | \& } | |
773 | \& } | |
774 | .Ve | |
775 | .SH "HASHES OF HASHES" | |
776 | .IX Header "HASHES OF HASHES" | |
777 | .Sh "Declaration of a \s-1HASH\s0 \s-1OF\s0 \s-1HASHES\s0" | |
778 | .IX Subsection "Declaration of a HASH OF HASHES" | |
779 | .Vb 16 | |
780 | \& %HoH = ( | |
781 | \& flintstones => { | |
782 | \& lead => "fred", | |
783 | \& pal => "barney", | |
784 | \& }, | |
785 | \& jetsons => { | |
786 | \& lead => "george", | |
787 | \& wife => "jane", | |
788 | \& "his boy" => "elroy", | |
789 | \& }, | |
790 | \& simpsons => { | |
791 | \& lead => "homer", | |
792 | \& wife => "marge", | |
793 | \& kid => "bart", | |
794 | \& }, | |
795 | \& ); | |
796 | .Ve | |
797 | .Sh "Generation of a \s-1HASH\s0 \s-1OF\s0 \s-1HASHES\s0" | |
798 | .IX Subsection "Generation of a HASH OF HASHES" | |
799 | .Vb 9 | |
800 | \& # reading from file | |
801 | \& # flintstones: lead=fred pal=barney wife=wilma pet=dino | |
802 | \& while ( <> ) { | |
803 | \& next unless s/^(.*?):\es*//; | |
804 | \& $who = $1; | |
805 | \& for $field ( split ) { | |
806 | \& ($key, $value) = split /=/, $field; | |
807 | \& $HoH{$who}{$key} = $value; | |
808 | \& } | |
809 | .Ve | |
810 | .PP | |
811 | .Vb 11 | |
812 | \& # reading from file; more temps | |
813 | \& while ( <> ) { | |
814 | \& next unless s/^(.*?):\es*//; | |
815 | \& $who = $1; | |
816 | \& $rec = {}; | |
817 | \& $HoH{$who} = $rec; | |
818 | \& for $field ( split ) { | |
819 | \& ($key, $value) = split /=/, $field; | |
820 | \& $rec->{$key} = $value; | |
821 | \& } | |
822 | \& } | |
823 | .Ve | |
824 | .PP | |
825 | .Vb 4 | |
826 | \& # calling a function that returns a key,value hash | |
827 | \& for $group ( "simpsons", "jetsons", "flintstones" ) { | |
828 | \& $HoH{$group} = { get_family($group) }; | |
829 | \& } | |
830 | .Ve | |
831 | .PP | |
832 | .Vb 5 | |
833 | \& # likewise, but using temps | |
834 | \& for $group ( "simpsons", "jetsons", "flintstones" ) { | |
835 | \& %members = get_family($group); | |
836 | \& $HoH{$group} = { %members }; | |
837 | \& } | |
838 | .Ve | |
839 | .PP | |
840 | .Vb 5 | |
841 | \& # append new members to an existing family | |
842 | \& %new_folks = ( | |
843 | \& wife => "wilma", | |
844 | \& pet => "dino", | |
845 | \& ); | |
846 | .Ve | |
847 | .PP | |
848 | .Vb 3 | |
849 | \& for $what (keys %new_folks) { | |
850 | \& $HoH{flintstones}{$what} = $new_folks{$what}; | |
851 | \& } | |
852 | .Ve | |
853 | .Sh "Access and Printing of a \s-1HASH\s0 \s-1OF\s0 \s-1HASHES\s0" | |
854 | .IX Subsection "Access and Printing of a HASH OF HASHES" | |
855 | .Vb 2 | |
856 | \& # one element | |
857 | \& $HoH{flintstones}{wife} = "wilma"; | |
858 | .Ve | |
859 | .PP | |
860 | .Vb 2 | |
861 | \& # another element | |
862 | \& $HoH{simpsons}{lead} =~ s/(\ew)/\eu$1/; | |
863 | .Ve | |
864 | .PP | |
865 | .Vb 8 | |
866 | \& # print the whole thing | |
867 | \& foreach $family ( keys %HoH ) { | |
868 | \& print "$family: { "; | |
869 | \& for $role ( keys %{ $HoH{$family} } ) { | |
870 | \& print "$role=$HoH{$family}{$role} "; | |
871 | \& } | |
872 | \& print "}\en"; | |
873 | \& } | |
874 | .Ve | |
875 | .PP | |
876 | .Vb 8 | |
877 | \& # print the whole thing somewhat sorted | |
878 | \& foreach $family ( sort keys %HoH ) { | |
879 | \& print "$family: { "; | |
880 | \& for $role ( sort keys %{ $HoH{$family} } ) { | |
881 | \& print "$role=$HoH{$family}{$role} "; | |
882 | \& } | |
883 | \& print "}\en"; | |
884 | \& } | |
885 | .Ve | |
886 | .PP | |
887 | .Vb 8 | |
888 | \& # print the whole thing sorted by number of members | |
889 | \& foreach $family ( sort { keys %{$HoH{$b}} <=> keys %{$HoH{$a}} } keys %HoH ) { | |
890 | \& print "$family: { "; | |
891 | \& for $role ( sort keys %{ $HoH{$family} } ) { | |
892 | \& print "$role=$HoH{$family}{$role} "; | |
893 | \& } | |
894 | \& print "}\en"; | |
895 | \& } | |
896 | .Ve | |
897 | .PP | |
898 | .Vb 3 | |
899 | \& # establish a sort order (rank) for each role | |
900 | \& $i = 0; | |
901 | \& for ( qw(lead wife son daughter pal pet) ) { $rank{$_} = ++$i } | |
902 | .Ve | |
903 | .PP | |
904 | .Vb 9 | |
905 | \& # now print the whole thing sorted by number of members | |
906 | \& foreach $family ( sort { keys %{ $HoH{$b} } <=> keys %{ $HoH{$a} } } keys %HoH ) { | |
907 | \& print "$family: { "; | |
908 | \& # and print these according to rank order | |
909 | \& for $role ( sort { $rank{$a} <=> $rank{$b} } keys %{ $HoH{$family} } ) { | |
910 | \& print "$role=$HoH{$family}{$role} "; | |
911 | \& } | |
912 | \& print "}\en"; | |
913 | \& } | |
914 | .Ve | |
915 | .SH "MORE ELABORATE RECORDS" | |
916 | .IX Header "MORE ELABORATE RECORDS" | |
917 | .Sh "Declaration of \s-1MORE\s0 \s-1ELABORATE\s0 \s-1RECORDS\s0" | |
918 | .IX Subsection "Declaration of MORE ELABORATE RECORDS" | |
919 | Here's a sample showing how to create and use a record whose fields are of | |
920 | many different sorts: | |
921 | .PP | |
922 | .Vb 8 | |
923 | \& $rec = { | |
924 | \& TEXT => $string, | |
925 | \& SEQUENCE => [ @old_values ], | |
926 | \& LOOKUP => { %some_table }, | |
927 | \& THATCODE => \e&some_function, | |
928 | \& THISCODE => sub { $_[0] ** $_[1] }, | |
929 | \& HANDLE => \e*STDOUT, | |
930 | \& }; | |
931 | .Ve | |
932 | .PP | |
933 | .Vb 1 | |
934 | \& print $rec->{TEXT}; | |
935 | .Ve | |
936 | .PP | |
937 | .Vb 2 | |
938 | \& print $rec->{SEQUENCE}[0]; | |
939 | \& $last = pop @ { $rec->{SEQUENCE} }; | |
940 | .Ve | |
941 | .PP | |
942 | .Vb 2 | |
943 | \& print $rec->{LOOKUP}{"key"}; | |
944 | \& ($first_k, $first_v) = each %{ $rec->{LOOKUP} }; | |
945 | .Ve | |
946 | .PP | |
947 | .Vb 2 | |
948 | \& $answer = $rec->{THATCODE}->($arg); | |
949 | \& $answer = $rec->{THISCODE}->($arg1, $arg2); | |
950 | .Ve | |
951 | .PP | |
952 | .Vb 2 | |
953 | \& # careful of extra block braces on fh ref | |
954 | \& print { $rec->{HANDLE} } "a string\en"; | |
955 | .Ve | |
956 | .PP | |
957 | .Vb 3 | |
958 | \& use FileHandle; | |
959 | \& $rec->{HANDLE}->autoflush(1); | |
960 | \& $rec->{HANDLE}->print(" a string\en"); | |
961 | .Ve | |
962 | .Sh "Declaration of a \s-1HASH\s0 \s-1OF\s0 \s-1COMPLEX\s0 \s-1RECORDS\s0" | |
963 | .IX Subsection "Declaration of a HASH OF COMPLEX RECORDS" | |
964 | .Vb 10 | |
965 | \& %TV = ( | |
966 | \& flintstones => { | |
967 | \& series => "flintstones", | |
968 | \& nights => [ qw(monday thursday friday) ], | |
969 | \& members => [ | |
970 | \& { name => "fred", role => "lead", age => 36, }, | |
971 | \& { name => "wilma", role => "wife", age => 31, }, | |
972 | \& { name => "pebbles", role => "kid", age => 4, }, | |
973 | \& ], | |
974 | \& }, | |
975 | .Ve | |
976 | .PP | |
977 | .Vb 9 | |
978 | \& jetsons => { | |
979 | \& series => "jetsons", | |
980 | \& nights => [ qw(wednesday saturday) ], | |
981 | \& members => [ | |
982 | \& { name => "george", role => "lead", age => 41, }, | |
983 | \& { name => "jane", role => "wife", age => 39, }, | |
984 | \& { name => "elroy", role => "kid", age => 9, }, | |
985 | \& ], | |
986 | \& }, | |
987 | .Ve | |
988 | .PP | |
989 | .Vb 10 | |
990 | \& simpsons => { | |
991 | \& series => "simpsons", | |
992 | \& nights => [ qw(monday) ], | |
993 | \& members => [ | |
994 | \& { name => "homer", role => "lead", age => 34, }, | |
995 | \& { name => "marge", role => "wife", age => 37, }, | |
996 | \& { name => "bart", role => "kid", age => 11, }, | |
997 | \& ], | |
998 | \& }, | |
999 | \& ); | |
1000 | .Ve | |
1001 | .Sh "Generation of a \s-1HASH\s0 \s-1OF\s0 \s-1COMPLEX\s0 \s-1RECORDS\s0" | |
1002 | .IX Subsection "Generation of a HASH OF COMPLEX RECORDS" | |
1003 | .Vb 5 | |
1004 | \& # reading from file | |
1005 | \& # this is most easily done by having the file itself be | |
1006 | \& # in the raw data format as shown above. perl is happy | |
1007 | \& # to parse complex data structures if declared as data, so | |
1008 | \& # sometimes it's easiest to do that | |
1009 | .Ve | |
1010 | .PP | |
1011 | .Vb 4 | |
1012 | \& # here's a piece by piece build up | |
1013 | \& $rec = {}; | |
1014 | \& $rec->{series} = "flintstones"; | |
1015 | \& $rec->{nights} = [ find_days() ]; | |
1016 | .Ve | |
1017 | .PP | |
1018 | .Vb 7 | |
1019 | \& @members = (); | |
1020 | \& # assume this file in field=value syntax | |
1021 | \& while (<>) { | |
1022 | \& %fields = split /[\es=]+/; | |
1023 | \& push @members, { %fields }; | |
1024 | \& } | |
1025 | \& $rec->{members} = [ @members ]; | |
1026 | .Ve | |
1027 | .PP | |
1028 | .Vb 2 | |
1029 | \& # now remember the whole thing | |
1030 | \& $TV{ $rec->{series} } = $rec; | |
1031 | .Ve | |
1032 | .PP | |
1033 | .Vb 19 | |
1034 | \& ########################################################### | |
1035 | \& # now, you might want to make interesting extra fields that | |
1036 | \& # include pointers back into the same data structure so if | |
1037 | \& # change one piece, it changes everywhere, like for example | |
1038 | \& # if you wanted a {kids} field that was a reference | |
1039 | \& # to an array of the kids' records without having duplicate | |
1040 | \& # records and thus update problems. | |
1041 | \& ########################################################### | |
1042 | \& foreach $family (keys %TV) { | |
1043 | \& $rec = $TV{$family}; # temp pointer | |
1044 | \& @kids = (); | |
1045 | \& for $person ( @{ $rec->{members} } ) { | |
1046 | \& if ($person->{role} =~ /kid|son|daughter/) { | |
1047 | \& push @kids, $person; | |
1048 | \& } | |
1049 | \& } | |
1050 | \& # REMEMBER: $rec and $TV{$family} point to same data!! | |
1051 | \& $rec->{kids} = [ @kids ]; | |
1052 | \& } | |
1053 | .Ve | |
1054 | .PP | |
1055 | .Vb 3 | |
1056 | \& # you copied the array, but the array itself contains pointers | |
1057 | \& # to uncopied objects. this means that if you make bart get | |
1058 | \& # older via | |
1059 | .Ve | |
1060 | .PP | |
1061 | .Vb 1 | |
1062 | \& $TV{simpsons}{kids}[0]{age}++; | |
1063 | .Ve | |
1064 | .PP | |
1065 | .Vb 2 | |
1066 | \& # then this would also change in | |
1067 | \& print $TV{simpsons}{members}[2]{age}; | |
1068 | .Ve | |
1069 | .PP | |
1070 | .Vb 2 | |
1071 | \& # because $TV{simpsons}{kids}[0] and $TV{simpsons}{members}[2] | |
1072 | \& # both point to the same underlying anonymous hash table | |
1073 | .Ve | |
1074 | .PP | |
1075 | .Vb 13 | |
1076 | \& # print the whole thing | |
1077 | \& foreach $family ( keys %TV ) { | |
1078 | \& print "the $family"; | |
1079 | \& print " is on during @{ $TV{$family}{nights} }\en"; | |
1080 | \& print "its members are:\en"; | |
1081 | \& for $who ( @{ $TV{$family}{members} } ) { | |
1082 | \& print " $who->{name} ($who->{role}), age $who->{age}\en"; | |
1083 | \& } | |
1084 | \& print "it turns out that $TV{$family}{lead} has "; | |
1085 | \& print scalar ( @{ $TV{$family}{kids} } ), " kids named "; | |
1086 | \& print join (", ", map { $_->{name} } @{ $TV{$family}{kids} } ); | |
1087 | \& print "\en"; | |
1088 | \& } | |
1089 | .Ve | |
1090 | .SH "Database Ties" | |
1091 | .IX Header "Database Ties" | |
1092 | You cannot easily tie a multilevel data structure (such as a hash of | |
1093 | hashes) to a dbm file. The first problem is that all but \s-1GDBM\s0 and | |
1094 | Berkeley \s-1DB\s0 have size limitations, but beyond that, you also have problems | |
1095 | with how references are to be represented on disk. One experimental | |
1096 | module that does partially attempt to address this need is the \s-1MLDBM\s0 | |
1097 | module. Check your nearest \s-1CPAN\s0 site as described in perlmodlib for | |
1098 | source code to \s-1MLDBM\s0. | |
1099 | .SH "SEE ALSO" | |
1100 | .IX Header "SEE ALSO" | |
1101 | \&\fIperlref\fR\|(1), \fIperllol\fR\|(1), \fIperldata\fR\|(1), \fIperlobj\fR\|(1) | |
1102 | .SH "AUTHOR" | |
1103 | .IX Header "AUTHOR" | |
1104 | Tom Christiansen <\fItchrist@perl.com\fR> | |
1105 | .PP | |
1106 | Last update: | |
1107 | Wed Oct 23 04:57:50 \s-1MET\s0 \s-1DST\s0 1996 |