File Coverage

blib/lib/Data/RenderAsTree.pm
Criterion Covered Total %
statement 141 181 77.9
branch 64 104 61.5
condition 19 29 65.5
subroutine 17 19 89.4
pod 3 5 60.0
total 244 338 72.1


line stmt bran cond sub pod time code
1             package Data::RenderAsTree;
2              
3 7     7   3403 use strict;
  7         10  
  7         209  
4 7     7   28 use warnings;
  7         9  
  7         149  
5              
6 7     7   3703 use Moo;
  7         77231  
  7         31  
7              
8 7     7   8086 use Scalar::Util qw/blessed reftype/;
  7         10  
  7         533  
9              
10 7     7   3993 use Set::Array;
  7         94360  
  7         267  
11              
12 7     7   3679 use Text::Truncate; # For truncstr().
  7         2852  
  7         327  
13              
14 7     7   5351 use Tree::DAG_Node;
  7         155053  
  7         289  
15              
16 7     7   4509 use Types::Standard qw/Any Bool Int Object Str/;
  7         367075  
  7         92  
17              
18             has clean_nodes =>
19             (
20             default => sub{return 0},
21             is => 'rw',
22             isa => Bool,
23             required => 0,
24             );
25              
26             has attributes =>
27             (
28             default => sub{return 0},
29             is => 'rw',
30             isa => Bool,
31             required => 0,
32             );
33              
34             has index_stack =>
35             (
36             default => sub{return Set::Array -> new},
37             is => 'rw',
38             isa => Object,
39             required => 0,
40             );
41              
42             has max_key_length =>
43             (
44             default => sub{return 10_000},
45             is => 'rw',
46             isa => Int,
47             required => 0,
48             );
49              
50             has max_value_length =>
51             (
52             default => sub{return 10_000},
53             is => 'rw',
54             isa => Int,
55             required => 0,
56             );
57              
58             has node_stack =>
59             (
60             default => sub{return Set::Array -> new},
61             is => 'rw',
62             isa => Object,
63             required => 0,
64             );
65              
66             has root =>
67             (
68             default => sub{return ''},
69             is => 'rw',
70             isa => Any,
71             required => 0,
72             );
73              
74             has title =>
75             (
76             default => sub{return 'Root'},
77             is => 'rw',
78             isa => Str,
79             required => 0,
80             );
81              
82             has uid =>
83             (
84             default => sub{return 0},
85             is => 'rw',
86             isa => Int,
87             required => 0,
88             );
89              
90             has verbose =>
91             (
92             default => sub{return 0},
93             is => 'rw',
94             isa => Bool,
95             required => 0,
96             );
97              
98             our $VERSION = '1.02';
99              
100             # ------------------------------------------------
101              
102             sub BUILD
103             {
104 7     7 0 199 my($self) = @_;
105 7         28 my($key_length) = $self -> max_key_length;
106 7         3434 my($value_length) = $self -> max_value_length;
107              
108 7 50 33     3468 $self -> max_key_length(30) if ( ($key_length < 1) || ($key_length > 10_000) );
109 7 50 33     160 $self -> max_value_length(30) if ( ($value_length < 1) || ($value_length > 10_000) );
110              
111             } # End of BUILD.
112              
113             # ------------------------------------------------
114              
115             sub _add_daughter
116             {
117 124     124   188 my($self, $name, $attributes) = @_;
118              
119 124 50       2129 print "Entered _add_daughter($name, $attributes)\n" if ($self -> verbose);
120              
121 124 50       652 $attributes = {} if (! $attributes);
122 124         210 $$attributes{name} = $name;
123 124         1958 $$attributes{uid} = $self -> uid($self -> uid + 1);
124 124         4538 $name = truncstr($name, $self -> max_key_length);
125 124         1663 my($node) = Tree::DAG_Node -> new({name => $name, attributes => $attributes});
126 124         5889 my($tos) = $self -> node_stack -> length - 1;
127              
128 124 50       5477 die "Stack is empty\n" if ($tos < 0);
129              
130 124         138 ${$self -> node_stack}[$tos] -> add_daughter($node);
  124         2478  
131              
132 124         6644 return $node;
133              
134             } # End of _add_daughter.
135              
136             # --------------------------------------------------
137              
138             sub clean_tree
139             {
140 0     0 0 0 my($self) = @_;
141              
142 0         0 my($attributes);
143             my($key);
144 0         0 my($name);
145 0         0 my($value);
146              
147             $self -> root -> walk_down
148             ({
149             callback => sub
150             {
151 0     0   0 my($node, $opt) = @_;
152 0         0 $name = $node -> name;
153 0         0 $attributes = $node -> attributes;
154              
155             # For for name is undef.
156              
157 0 0       0 $node -> name('') if (! defined $name);
158              
159             # Fix for attribute name is undef.
160              
161 0 0       0 if (exists $$attributes{undef})
162             {
163 0 0       0 if (! exists $$attributes{''})
164             {
165 0         0 $$attributes{''} = $$attributes{undef};
166             }
167              
168 0         0 delete $$attributes{undef};
169             }
170              
171             # Fix for attribute value is undef.
172              
173 0         0 for $key (keys %$attributes)
174             {
175 0         0 $value = $$attributes{$key};
176 0 0       0 $value = '' if (! defined $value);
177 0         0 $$attributes{$key} = $value;
178             }
179              
180 0         0 $node -> attributes($attributes);
181              
182 0         0 return 1; # Keep walking.
183             },
184 0         0 _depth => 0,
185             });
186              
187             } # End of clean_tree.
188              
189             # ------------------------------------------------
190              
191             sub _process_arrayref
192             {
193 19     19   37 my($self, $value) = @_;
194              
195 19 50       298 print "Entered _process_arrayref($value)\n" if ($self -> verbose);
196              
197 19         1291 my($index) = $self -> index_stack -> last;
198 19         786 my($parent) = $self -> _process_scalar("$index = []", 'ARRAY');
199              
200 19         339 $self -> node_stack -> push($parent);
201              
202 19         758 $index = -1;
203              
204 19         27 my($bless_type);
205             my($node);
206 0         0 my($ref_type);
207              
208 19         30 for my $item (@$value)
209             {
210 37         34 $index++;
211              
212 37   50     151 $bless_type = blessed($item) || '';
213 37   100     104 $ref_type = reftype($item) || 'VALUE';
214              
215 37 50       54 if ($bless_type)
216             {
217 0         0 $self -> node_stack -> push($self -> _process_scalar("Class = $bless_type", 'BLESS') );
218             }
219              
220 37 100       90 if ($ref_type eq 'ARRAY')
    100          
    50          
221             {
222 7         128 $self -> index_stack -> push($index);
223 7         324 $self -> _process_arrayref($item);
224              
225 7         383 $index = $self -> index_stack -> pop;
226             }
227             elsif ($ref_type eq 'HASH')
228             {
229 4         8 $self -> _process_hashref($item);
230             }
231             elsif ($ref_type eq 'SCALAR')
232             {
233 0         0 $self -> _process_scalar($item);
234             }
235             else
236             {
237 26 50       485 $self -> _process_scalar("$index = " . (defined($item) ? truncstr($item, $self -> max_value_length) : 'undef') );
238             }
239              
240 37 50       538 $node = $self -> node_stack -> pop if ($bless_type);
241             }
242              
243 19         356 $node = $self -> node_stack -> pop;
244              
245             } # End of _process_arrayref;
246              
247             # ------------------------------------------------
248              
249             sub _process_hashref
250             {
251 27     27   49 my($self, $data) = @_;
252 27         28 my($index) = -1;
253              
254 27 50       534 print "Entered _process_hashref($data)\n" if ($self -> verbose);
255              
256 27         637 my($parent) = $self -> _process_scalar('{}', 'HASH');
257              
258 27         570 $self -> node_stack -> push($parent);
259              
260 27         1190 my($bless_type);
261             my($node);
262 0         0 my($ref_type);
263 0         0 my($value);
264              
265 27         129 for my $key (sort keys %$data)
266             {
267 46         163 $index++;
268              
269 46         66 $value = $$data{$key};
270 46   100     197 $bless_type = blessed($value) || '';
271 46   100     140 $ref_type = reftype($value) || 'VALUE';
272 46 100       97 $key = "$key = {}" if ($ref_type eq 'HASH');
273              
274             # Values for use_value:
275             # 0: No, the value of value is undef. Ignore it.
276             # 1: Yes, The value may be undef, but use it.
277              
278 46         171 $node = $self -> _add_daughter
279             (
280             $key,
281             {type => $ref_type, use_value => 1, value => $value}
282             );
283              
284 46 100       96 if ($bless_type)
285             {
286 1         17 $self -> node_stack -> push($node);
287              
288 1         51 $node = $self -> _process_scalar("Class = $bless_type", 'BLESS');
289             }
290              
291 46         991 $self -> node_stack -> push($node);
292              
293 46 100       2441 if ($ref_type eq 'ARRAY')
    100          
    50          
294             {
295 4         73 $self -> index_stack -> push($index);
296 4         174 $self -> _process_arrayref($value);
297              
298 4         235 $index = $self -> index_stack -> pop;
299             }
300             elsif ($ref_type =~ /CODE|REF|SCALAR|VALUE/)
301             {
302             # Do nothing, except for scalars. sub _process_tree() will combine $key and $value.
303              
304 31 100       73 if ($ref_type eq 'SCALAR')
305             {
306 1         4 $self -> _add_daughter
307             (
308             $value,
309             {type => $ref_type, use_value => 1, value => $$value}
310             );
311             }
312             }
313             elsif ($ref_type eq 'HASH')
314             {
315 11         37 $self -> _process_hashref($value);
316             }
317             else
318             {
319 0         0 die "Sub _process_hashref() cannot handle the ref_type: $ref_type. \n";
320             }
321              
322 46         1552 $node = $self -> node_stack -> pop;
323 46 100       2204 $node = $self -> node_stack -> pop if ($bless_type);
324              
325             # TODO: Why don't we need this in _process_arrayref()?
326             # And ... Do we need to check after each pop above?
327              
328 46 50       154 $self -> node_stack -> push($self -> root) if ($node -> is_root);
329             }
330              
331 27         703 $self -> node_stack -> pop;
332              
333             } # End of _process_hashref.
334              
335             # ------------------------------------------------
336              
337             sub _process_scalar
338             {
339 77     77   408 my($self, $value, $type) = @_;
340 77   100     194 $type ||= 'SCALAR';
341              
342 77 50       1184 print "Entered _process_scalar($value, $type)\n" if ($self -> verbose);
343              
344             # Values for use_value:
345             # 0: No, the value of value is undef. Ignore it.
346             # 1: Yes, The value may be undef, but use it.
347              
348 77         2445 return $self -> _add_daughter
349             (
350             $value,
351             {type => $type, use_value => 0, value => undef}
352             );
353              
354             } # End of _process_scalar.
355              
356             # ------------------------------------------------
357              
358             sub process_tree
359             {
360 23     23 1 31 my($self) = @_;
361              
362 23 50       435 if ($self -> verbose)
363             {
364 0         0 print "Entered process_tree(). Printing tree before walk_down ...\n";
365 0         0 print join("\n", @{$self -> root -> tree2string({no_attributes => 0})}), "\n";
  0         0  
366 0         0 print '-' x 50, "\n";
367             }
368              
369 23         134 my($attributes);
370 23         22 my($ignore_value, $id);
371 0         0 my($key);
372 0         0 my($name);
373 0         0 my($ref_type);
374 0         0 my($type);
375 0         0 my($uid, $use_value);
376 0         0 my($value);
377              
378             $self -> root -> walk_down
379             ({
380             callback => sub
381             {
382 147     147   2831 my($node, $opt) = @_;
383              
384             # Ignore the root, and keep walking.
385              
386 147 100       240 return 1 if ($node -> is_root);
387              
388 124         814 $name = $node -> name;
389 124         507 $attributes = $node -> attributes;
390 124         422 $type = $$attributes{type};
391 124 50       394 $ref_type = ($type =~ /^(\w+)/) ? $1 : $type; # Ignores '(0x12345678)'.
392 124         138 $uid = $$attributes{uid};
393 124         123 $use_value = $$attributes{use_value};
394 124         111 $value = $$attributes{value};
395 124         148 $key = "$ref_type $uid";
396              
397 124 50 66     605 if (defined($value) && $$opt{seen}{$value})
    50          
    50          
    100          
    100          
398             {
399 0 0 0     0 $id = ( ($ref_type eq 'SCALAR') || ($key =~ /^ARRAY|BLESS|HASH/) ) ? $key : "$key -> $$opt{seen}{$value}";
400             }
401             elsif ($ref_type eq 'CODE')
402             {
403 0         0 $id = $key;
404 0 0       0 $name = defined($value) ? "$name = $value" : $name;
405             }
406             elsif ($ref_type eq 'REF')
407             {
408 0 0       0 $id = defined($value) ? $$opt{seen}{$$value} ? "$key -> $$opt{seen}{$$value}" : $key : $key;
    0          
409             }
410             elsif ($ref_type eq 'VALUE')
411             {
412 32         29 $id = $key;
413 32 50       52 $name = defined($name) ? $name : 'undef';
414 32 100       686 $name .= ' = ' . truncstr(defined($value) ? $value : 'undef', $self -> max_value_length) if ($use_value);
    100          
415             }
416             elsif ($ref_type eq 'SCALAR')
417             {
418 29         25 $id = $key;
419 29 50       37 $name = defined($name) ? $name : 'undef';
420 29 50       90 $name .= ' = ' . truncstr(defined($value) ? $value : 'undef', $self -> max_value_length) if ($use_value);
    100          
421             }
422             else
423             {
424 63         68 $id = $key;
425             }
426              
427 124         666 $node -> name("$name [$id]");
428              
429 124 100 66     754 $$opt{seen}{$value} = $id if (defined($value) && ! defined $$opt{seen}{$value});
430              
431             # Keep walking.
432              
433 124         186 return 1;
434             },
435 23         370 _depth => 0,
436             seen => {},
437             });
438              
439             } # End of process_tree.
440              
441             # ------------------------------------------------
442              
443             sub render
444             {
445 23     23 1 19735 my($self, $s) = @_;
446              
447 23         58 $self -> run($s);
448              
449 23         770 return $self -> root -> tree2string({no_attributes => 1 - $self -> attributes});
450              
451             } # End of render.
452              
453             # ------------------------------------------------
454              
455             sub run
456             {
457 23     23 1 29 my($self, $s) = @_;
458 23 100       59 $s = defined($s) ? $s : 'undef';
459              
460 23         463 $self -> root
461             (
462             Tree::DAG_Node -> new
463             ({
464             attributes => {type => '', uid => $self -> uid, value => ''},
465             name => $self -> title,
466             })
467             );
468 23         12179 $self -> node_stack -> push($self -> root);
469 23         5583 $self -> index_stack -> push(0);
470              
471 23   100     4421 my($bless_type) = blessed($s) || '';
472 23   100     86 my($ref_type) = reftype($s) || 'VALUE';
473              
474 23 100       54 if ($bless_type)
475             {
476 1         18 $self -> node_stack -> push($self -> _process_scalar("Class = $bless_type", 'BLESS') );
477             }
478              
479 23 100       117 if ($ref_type eq 'ARRAY')
    100          
    50          
480             {
481 8         21 $self -> _process_arrayref($s);
482             }
483             elsif ($ref_type eq 'HASH')
484             {
485 12         33 $self -> _process_hashref($s);
486             }
487             elsif ($ref_type =~ /REF|SCALAR|VALUE/)
488             {
489 3         12 $self -> _process_scalar($s, $ref_type);
490             }
491             else
492             {
493 0         0 die "Sub render() cannot handle the ref_type: $ref_type. \n";
494             }
495              
496 23         927 $self -> process_tree;
497 23 50       1003 $self -> clean_tree if ($self -> clean_nodes);
498              
499             # Clean up in case user reuses this object.
500              
501 23         3719 $self -> node_stack -> pop;
502 23         1490 $self -> index_stack -> pop;
503 23 100       907 $self -> node_stack -> pop if ($bless_type);
504 23         451 $self -> uid(0);
505              
506             } # End of run.
507              
508             # ------------------------------------------------
509              
510             1;
511              
512             =pod
513              
514             =head1 NAME
515              
516             C - Render any data structure as an object of type Tree::DAG_Node
517              
518             =head1 Synopsis
519              
520             This is scripts/synopsis.pl:
521              
522             #!/usr/bin/env perl
523              
524             use strict;
525             use warnings;
526              
527             use Data::RenderAsTree;
528              
529             use Tree::DAG_Node;
530              
531             # ------------------------------------------------
532              
533             my($sub) = sub {};
534             my($s) =
535             {
536             A =>
537             {
538             a => {},
539             bbbbbb => $sub,
540             c123 => $sub,
541             d => \$sub,
542             },
543             B => [qw(element_1 element_2 element_3)],
544             C =>
545             {
546             b =>
547             {
548             a =>
549             {
550             a => {},
551             b => sub {},
552             c => '429999999999999999999999999999999999999999999999',
553             }
554             }
555             },
556             DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD => 'd',
557             Object => Tree::DAG_Node -> new({name => 'A tree', attributes => {one => 1} }),
558             Ref2Scalar => \'A shortish string', # Use ' in comment for UltraEdit hiliting.
559             };
560             my($result) = Data::RenderAsTree -> new
561             (
562             attributes => 0,
563             max_key_length => 25,
564             max_value_length => 20,
565             title => 'Synopsis',
566             verbose => 0,
567             ) -> render($s);
568              
569             print join("\n", @$result), "\n";
570              
571             See the L for a discussion as to whether you should call L or L.
572              
573             This is the output of scripts/synopsis.pl:
574              
575             Synopsis
576             |--- {} [HASH 1]
577             |--- A = {} [HASH 2]
578             | |--- {} [HASH 3]
579             | |--- a = {} [HASH 4]
580             | | |--- {} [HASH 5]
581             | |--- bbbbbb = CODE(0x1c93e30) [CODE 6]
582             | |--- c123 [CODE 7 -> CODE 6]
583             | |--- d [REF 8 -> CODE 6]
584             |--- B [ARRAY 9]
585             | |--- 1 = [] [ARRAY 10]
586             | |--- 0 = element_1 [SCALAR 11]
587             | |--- 1 = element_2 [SCALAR 12]
588             | |--- 2 = element_3 [SCALAR 13]
589             |--- C = {} [HASH 14]
590             | |--- {} [HASH 15]
591             | |--- b = {} [HASH 16]
592             | |--- {} [HASH 17]
593             | |--- a = {} [HASH 18]
594             | |--- {} [HASH 19]
595             | |--- a = {} [HASH 20]
596             | | |--- {} [HASH 21]
597             | |--- b = CODE(0x2475c68) [CODE 22]
598             | |--- c = 42999999999999999... [VALUE 23]
599             |--- DDDDDDDDDDDDDDDDDDDDDD... = d [VALUE 24]
600             |--- Object = {} [HASH 25]
601             | |--- Class = Tree::DAG_Node [BLESS 26]
602             | |--- {} [HASH 27]
603             | |--- attributes = {} [HASH 28]
604             | | |--- {} [HASH 29]
605             | | |--- one = 1 [VALUE 30]
606             | |--- daughters [ARRAY 31]
607             | | |--- 1 = [] [ARRAY 32]
608             | |--- mother = undef [VALUE 33]
609             | |--- name = A tree [VALUE 34]
610             |--- Ref2Scalar = SCALAR(0x230a230) [SCALAR 35]
611             |--- SCALAR(0x230a230) = A shortish string [SCALAR 36]
612              
613             =head1 Description
614              
615             L provides a mechanism to display a Perl data structure.
616              
617             The data supplied to L is stored in an object of type L.
618              
619             C returns an arrayref by calling C's C method, so you can
620             just print the return value as a string by using code as in synopsis.pl above.
621              
622             It also means you can display as much or as little of the result as you wish, by printing a range
623             of array elements.
624              
625             Hash key lengths can be limited by L, and hash value lengths can be limited
626             by L.
627              
628             For sub-classing, see L.
629              
630             The module serves as a simple replacement for L, but without the huge set of
631             features.
632              
633             For sample code, see these programs in the scripts/ directory of the distro:
634              
635             =over 4
636              
637             =item o array.pl
638              
639             =item o bless.pl
640              
641             =item o hash.pl
642              
643             =item o mixup.pl
644              
645             =item o ref.pl
646              
647             =item o synopsis.pl
648              
649             =back
650              
651             See also the test files t/*.t, which are basically copies of the above. And that means, like the
652             *.pl above, all expected output is given in the source code.
653              
654             Lastly, see the L for details such as how to process the output tree yourself.
655              
656             =head1 Distributions
657              
658             This module is available as a Unix-style distro (*.tgz).
659              
660             See L
661             for help on unpacking and installing distros.
662              
663             =head1 Installation
664              
665             Install L as you would for any C module:
666              
667             Run:
668              
669             cpanm Data::RenderAsTree
670              
671             or run:
672              
673             sudo cpan Data::RenderAsTree
674              
675             or unpack the distro, and then either:
676              
677             perl Build.PL
678             ./Build
679             ./Build test
680             sudo ./Build install
681              
682             or:
683              
684             perl Makefile.PL
685             make (or dmake or nmake)
686             make test
687             make install
688              
689             =head1 Constructor and Initialization
690              
691             C is called as C<< my($g2m) = Data::RenderAsTree -> new(k1 => v1, k2 => v2, ...) >>.
692              
693             It returns a new object of type C.
694              
695             Key-value pairs accepted in the parameter list (see corresponding methods for details
696             [e.g. L]):
697              
698             =over 4
699              
700             =item o attributes => $Boolean
701              
702             This is a debugging aid. When set to 1, metadata attached to each tree node is included in the
703             output.
704              
705             Default: 0.
706              
707             =item o clean_nodes => $Boolean
708              
709             Clean up nodes before printing, by changing the node's name to '' (the empty string) if it's undef,
710             and by changing to '' any node attribute value which is undef.
711              
712             Set to 1 to activate option.
713              
714             Default: 0.
715              
716             =item o max_key_length => $int
717              
718             Use this to limit the lengths of hash keys.
719              
720             Default: 10_000.
721              
722             =item o max_value_length => $int
723              
724             Use this to limit the lengths of hash values.
725              
726             Default: 10_000.
727              
728             =item o title => $s
729              
730             Use this to set the name of the root node in the tree.
731              
732             Default: 'Root'.
733              
734             =back
735              
736             =head1 Methods
737              
738             =head2 attributes([$Boolean])
739              
740             Here, the [] indicate an optional parameter.
741              
742             Gets or sets the attributes option.
743              
744             Note: The value passed to L's C method is (1 - $Boolean).
745              
746             C is a parameter to L.
747              
748             =head2 clean_nodes([$Boolean])
749              
750             Gets or sets the value of the C option.
751              
752             This stops undef warnings when printing (i.e. when calling the tree's tree2string() method).
753              
754             Values:
755              
756             =over 4
757              
758             =item o 0
759              
760             Do not clean up nodes.
761              
762             =item o 1
763              
764             Clean up nodes by doing both these:
765              
766             =over 4
767              
768             =item o The node's name
769              
770             Change the node's name to '' (the empty string) if it's undef.
771              
772             =item o The node's attribute values
773              
774             Change to '' any node attribute value which is undef.
775              
776             =back
777              
778             =back
779              
780             =head2 max_key_length([$int])
781              
782             Here, the [] indicate an optional parameter.
783              
784             Gets or sets the maximum string length displayed for hash keys.
785              
786             C is a parameter to L.
787              
788             =head2 max_key_length([$int])
789              
790             Here, the [] indicate an optional parameter.
791              
792             Gets or sets the maximum string length displayed for hash values.
793              
794             C is a parameter to L.
795              
796             =head2 new()
797              
798             See L for details on the parameters accepted by L.
799              
800             =head2 process_tree()
801              
802             Just before L returns, it calls C, while walks the tree and adjusts
803             various bits of data attached to each node in the tree.
804              
805             If sub-classing this module, e.g. to change the precise text displayed, I recommend concentrating
806             your efforts on this method.
807              
808             Also, see the answer to the first question in the L.
809              
810             =head2 render($s)
811              
812             Renders $s into an object of type L.
813              
814             Returns an arrayref after calling the C method for L.
815              
816             See L for a typical usage.
817              
818             See also L, which returns the root of the tree.
819              
820             The choice of calling C or C is discussed in the L.
821              
822             =head2 root()
823              
824             Returns the root node in the tree, which is an object of type L.
825              
826             =head2 run($s)
827              
828             Renders $s into an object of type L.
829              
830             Returns the root of the tree.
831              
832             See also L, which returns an arrayref of the tree's data.
833              
834             The choice of calling C or C is discussed in the L.
835              
836             =head2 title([$s])
837              
838             Here, the [] indicate an optional parameter.
839              
840             Gets or sets the title, which is the name of the root node in the tree.
841              
842             C is a parameter to L</new()>. </td> </tr> <tr> <td class="h" > <a name="843">843</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="844">844</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 verbose([$Boolean]) </td> </tr> <tr> <td class="h" > <a name="845">845</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="846">846</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Here, the [] indicate an optional parameter. </td> </tr> <tr> <td class="h" > <a name="847">847</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="848">848</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Gets or sets the verbose option, which prints a message upon entry to each method, with parameters, </td> </tr> <tr> <td class="h" > <a name="849">849</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> and prints the tree at the start of L</process_tree()>. </td> </tr> <tr> <td class="h" > <a name="850">850</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="851">851</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> C<verbose> is a parameter to L</new()>. </td> </tr> <tr> <td class="h" > <a name="852">852</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="853">853</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 FAQ </td> </tr> <tr> <td class="h" > <a name="854">854</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="855">855</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Can I process the tree myself? </td> </tr> <tr> <td class="h" > <a name="856">856</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="857">857</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Sure. Just call L</render($s)> and then L</root($s)> to get the root of the tree, and process it </td> </tr> <tr> <td class="h" > <a name="858">858</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> any way you wish. </td> </tr> <tr> <td class="h" > <a name="859">859</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="860">860</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Otherwise, call L</root($s)>, which returns the root directly. </td> </tr> <tr> <td class="h" > <a name="861">861</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="862">862</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> See the next question for help in choosing between C<render()> and C<root()>. </td> </tr> <tr> <td class="h" > <a name="863">863</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="864">864</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> See L</process_tree()> for sample code. More information is in the docs for L<Tree::DAG_Node> </td> </tr> <tr> <td class="h" > <a name="865">865</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> especially under the discussion of C<walk_down()>. </td> </tr> <tr> <td class="h" > <a name="866">866</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="867">867</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 How do I choose between calling C<render()> and C<root()>? </td> </tr> <tr> <td class="h" > <a name="868">868</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="869">869</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L</render($s)> automatically calls L<Tree::DAG_Node>'s C<tree2string()> method, which you may not </td> </tr> <tr> <td class="h" > <a name="870">870</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> want. </td> </tr> <tr> <td class="h" > <a name="871">871</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="872">872</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> For instance, the tree might have undef as the name of node, or the value of an attribute, so that </td> </tr> <tr> <td class="h" > <a name="873">873</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> calling C<tree2string()> triggers undefined variable warnings when converting the node's attributes </td> </tr> <tr> <td class="h" > <a name="874">874</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> to a string. </td> </tr> <tr> <td class="h" > <a name="875">875</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="876">876</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> With L</run($s)>, since C<tree2string()> is not called, you have time to process the tree yourself, </td> </tr> <tr> <td class="h" > <a name="877">877</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> cleaning up the nodes, before converting it to an arrayref of strings by calling C<tree2string()> </td> </tr> <tr> <td class="h" > <a name="878">878</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> directly. Indeed, with C<run()> you may never call C<tree2string()> at all. </td> </tr> <tr> <td class="h" > <a name="879">879</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="880">880</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Users of L<Marpa::R2> would normally call L</run($s)>. See L<MarpaX::Languages::Lua::Parser> for </td> </tr> <tr> <td class="h" > <a name="881">881</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> sample code, where node names of undef are the reason for this choice. </td> </tr> <tr> <td class="h" > <a name="882">882</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="883">883</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 What are the attributes of the tree nodes? </td> </tr> <tr> <td class="h" > <a name="884">884</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="885">885</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Firslty, each node has a name, which you can set or get with the C<name([$new_name])> method. Here, </td> </tr> <tr> <td class="h" > <a name="886">886</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> [] refer to an optional parameter. </td> </tr> <tr> <td class="h" > <a name="887">887</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="888">888</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Secondly, the attributes of each node are held in a hashref, getable and setable with the </td> </tr> <tr> <td class="h" > <a name="889">889</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> C<attributes([$hashref])> method. The returned hashref has these (key => value) pairs: </td> </tr> <tr> <td class="h" > <a name="890">890</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="891">891</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="892">892</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="893">893</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o name => $string </td> </tr> <tr> <td class="h" > <a name="894">894</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="895">895</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This is a copy of the name of the node. It's here because L</process_tree()> changes the name of </td> </tr> <tr> <td class="h" > <a name="896">896</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> some nodes as it walks the tree. </td> </tr> <tr> <td class="h" > <a name="897">897</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="898">898</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o type => $string </td> </tr> <tr> <td class="h" > <a name="899">899</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="900">900</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This is the C<reftype()> (from the module L</Scalar::Util>) of the value (see the C<value> key, </td> </tr> <tr> <td class="h" > <a name="901">901</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> below), or one of various strings I use, and hence has values like: </td> </tr> <tr> <td class="h" > <a name="902">902</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="903">903</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over 4 </td> </tr> <tr> <td class="h" > <a name="904">904</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="905">905</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o ARRAY </td> </tr> <tr> <td class="h" > <a name="906">906</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="907">907</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is an arrayref. </td> </tr> <tr> <td class="h" > <a name="908">908</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="909">909</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o BLESS </td> </tr> <tr> <td class="h" > <a name="910">910</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="911">911</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is blessed into a class, who name is in the value. </td> </tr> <tr> <td class="h" > <a name="912">912</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="913">913</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o CODE </td> </tr> <tr> <td class="h" > <a name="914">914</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="915">915</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is a coderef. </td> </tr> <tr> <td class="h" > <a name="916">916</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="917">917</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o HASH </td> </tr> <tr> <td class="h" > <a name="918">918</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="919">919</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is a hashref. </td> </tr> <tr> <td class="h" > <a name="920">920</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="921">921</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o REF </td> </tr> <tr> <td class="h" > <a name="922">922</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="923">923</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is presumably a generic reference. I could not see an explanation which I skimmed the </td> </tr> <tr> <td class="h" > <a name="924">924</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> output of 'perldoc perlref'. </td> </tr> <tr> <td class="h" > <a name="925">925</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="926">926</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o SCALAR </td> </tr> <tr> <td class="h" > <a name="927">927</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="928">928</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is a scalarref. </td> </tr> <tr> <td class="h" > <a name="929">929</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="930">930</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o VALUE </td> </tr> <tr> <td class="h" > <a name="931">931</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="932">932</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The value is just a literal value. </td> </tr> <tr> <td class="h" > <a name="933">933</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="934">934</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> I did not use LITERAL because the 1-letter abbreviation 'L' clashes with the 1-letter abbreviation </td> </tr> <tr> <td class="h" > <a name="935">935</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> of 'LVALUE', which C<reftype()> can return. </td> </tr> <tr> <td class="h" > <a name="936">936</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="937">937</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="938">938</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="939">939</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Other values returned by C<reftype()> are not used by this module. </td> </tr> <tr> <td class="h" > <a name="940">940</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="941">941</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o uid => $integer </td> </tr> <tr> <td class="h" > <a name="942">942</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="943">943</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Each node in the tree has a unique integer identifier, counting from 1 up. </td> </tr> <tr> <td class="h" > <a name="944">944</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="945">945</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o use_value => $Boolean </td> </tr> <tr> <td class="h" > <a name="946">946</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="947">947</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Node values (see next point) can be undef, and this flag serves the following purpose: </td> </tr> <tr> <td class="h" > <a name="948">948</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="949">949</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =over </td> </tr> <tr> <td class="h" > <a name="950">950</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="951">951</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o Zero </td> </tr> <tr> <td class="h" > <a name="952">952</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="953">953</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Do not use the value. It's undef, and set by the code, and thus not a real node's value. </td> </tr> <tr> <td class="h" > <a name="954">954</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="955">955</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o One </td> </tr> <tr> <td class="h" > <a name="956">956</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="957">957</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The node's value really is undef, or any other value. Use it in the output. </td> </tr> <tr> <td class="h" > <a name="958">958</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="959">959</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="960">960</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="961">961</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =item o value => $string </td> </tr> <tr> <td class="h" > <a name="962">962</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="963">963</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Finally, the actual value of the node. </td> </tr> <tr> <td class="h" > <a name="964">964</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="965">965</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =back </td> </tr> <tr> <td class="h" > <a name="966">966</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="967">967</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Why are there so many levels in the output? </td> </tr> <tr> <td class="h" > <a name="968">968</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="969">969</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Or: Couldn't you cut some cases showing '{}' and '[]'? </td> </tr> <tr> <td class="h" > <a name="970">970</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="971">971</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Cutting them introduces other problems, especially when the input is a set of nested arrayrefs. </td> </tr> <tr> <td class="h" > <a name="972">972</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="973">973</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> See scripts/array.pl, example 4 (hash key 4), for such a case. </td> </tr> <tr> <td class="h" > <a name="974">974</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="975">975</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Why do you decorate the output with e.g. [HASH 1] and not [H1]? </td> </tr> <tr> <td class="h" > <a name="976">976</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="977">977</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> I feel the style [H1] used by L<Data::TreeDumper> is unnecessarily cryptic. </td> </tr> <tr> <td class="h" > <a name="978">978</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="979">979</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 I found a problem with the output of synopsis.pl! </td> </tr> <tr> <td class="h" > <a name="980">980</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="981">981</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> It says: </td> </tr> <tr> <td class="h" > <a name="982">982</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="983">983</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> |--- B [ARRAY 9] </td> </tr> <tr> <td class="h" > <a name="984">984</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> | |--- 1 = [] [ARRAY 10] </td> </tr> <tr> <td class="h" > <a name="985">985</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="986">986</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Why is there a '1 = []' in there? </td> </tr> <tr> <td class="h" > <a name="987">987</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="988">988</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Firstly, note that C<hash> keys are returned in sorted order. </td> </tr> <tr> <td class="h" > <a name="989">989</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="990">990</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> And, for C<hash> keys, that integer counts them, so C<A> would have gotten a 0, and C<C> would get </td> </tr> <tr> <td class="h" > <a name="991">991</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> a 2, if they pointed to arrayrefs. </td> </tr> <tr> <td class="h" > <a name="992">992</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="993">993</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 Why did you use Text::Truncate? </td> </tr> <tr> <td class="h" > <a name="994">994</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="995">995</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The major alternatives are L<String::Truncate> and L<Text::Elide>, or re-inventing the wheel. </td> </tr> <tr> <td class="h" > <a name="996">996</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="997">997</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The first module seems too complex, and the second truncates to whole words, which makes sense in </td> </tr> <tr> <td class="h" > <a name="998">998</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> some applications, but not for dumping raw data. </td> </tr> <tr> <td class="h" > <a name="999">999</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1000">1000</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head2 How would I go about sub-classing this module? </td> </tr> <tr> <td class="h" > <a name="1001">1001</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1002">1002</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> This matter is discussed in the notes for method L</process_tree()>. </td> </tr> <tr> <td class="h" > <a name="1003">1003</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1004">1004</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 See Also </td> </tr> <tr> <td class="h" > <a name="1005">1005</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1006">1006</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<Data::TreeDumper>. </td> </tr> <tr> <td class="h" > <a name="1007">1007</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1008">1008</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Machine-Readable Change Log </td> </tr> <tr> <td class="h" > <a name="1009">1009</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1010">1010</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The file Changes was converted into Changelog.ini by L<Module::Metadata::Changes>. </td> </tr> <tr> <td class="h" > <a name="1011">1011</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1012">1012</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Version Numbers </td> </tr> <tr> <td class="h" > <a name="1013">1013</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1014">1014</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Version numbers < 1.00 represent development versions. From 1.00 up, they are production versions. </td> </tr> <tr> <td class="h" > <a name="1015">1015</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1016">1016</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Repository </td> </tr> <tr> <td class="h" > <a name="1017">1017</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1018">1018</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<https://github.com/ronsavage/Data-RenderAsTree> </td> </tr> <tr> <td class="h" > <a name="1019">1019</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1020">1020</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Support </td> </tr> <tr> <td class="h" > <a name="1021">1021</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1022">1022</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Email the author, or log a bug on RT: </td> </tr> <tr> <td class="h" > <a name="1023">1023</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1024">1024</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<https://rt.cpan.org/Public/Dist/Display.html?Name=Data::RenderAsTree>. </td> </tr> <tr> <td class="h" > <a name="1025">1025</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1026">1026</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Author </td> </tr> <tr> <td class="h" > <a name="1027">1027</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1028">1028</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> L<Data::RenderAsTree> was written by Ron Savage I<E<lt>ron@savage.net.auE<gt>> in 2015. </td> </tr> <tr> <td class="h" > <a name="1029">1029</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1030">1030</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> My homepage: L<http://savage.net.au/>. </td> </tr> <tr> <td class="h" > <a name="1031">1031</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1032">1032</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =head1 Copyright </td> </tr> <tr> <td class="h" > <a name="1033">1033</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1034">1034</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> Australian copyright (c) 2015, Ron Savage. </td> </tr> <tr> <td class="h" > <a name="1035">1035</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1036">1036</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> All Programs of mine are 'OSI Certified Open Source Software'; </td> </tr> <tr> <td class="h" > <a name="1037">1037</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> you can redistribute them and/or modify them under the terms of </td> </tr> <tr> <td class="h" > <a name="1038">1038</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> The Artistic License 2.0, a copy of which is available at: </td> </tr> <tr> <td class="h" > <a name="1039">1039</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> http://opensource.org/licenses/alphabetical. </td> </tr> <tr> <td class="h" > <a name="1040">1040</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s">   </td> </tr> <tr> <td class="h" > <a name="1041">1041</a> </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td >   </td> <td class="s"> =cut </td> </tr> </table> </body> </html>