The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Role::TinyCommons::Tree::FromStruct - Role that provides methods to build tree object from data structure

VERSION

This document describes version 0.129 of Role::TinyCommons::Tree::FromStruct (from Perl distribution RoleBundle-TinyCommons-Tree), released on 2021-10-07.

MIXED IN ROLES

Role::TinyCommons::Tree::NodeMethods

PROVIDED METHODS

new_from_struct($struct) => obj

Construct a tree object from a data structure $struct. The data structure must be a hash. Its keys must contain zero or more attributes to set the attributes of the to-be-created tree node. Keys that begin with underscore (_), however, contains special instructions.

Example usage:

 my $family_tree = My::Person->new_from_struct({
     name => 'Andi', age => 64, _children => [
         {name => 'Budi', age => 30},
         {name => 'Cinta', _class => 'My::MarriedPerson', _children => [
              {name => 'Deni'},
              {name => 'Eno'},
          ]},
     ]});

In this example, new_from_struct will create the first (root) node using:

 My::Person->new(name => 'Andi', age => 64)

To customize how a node is instantiated, there are several ways. First, if you want to use another class, you can put a _class key in your struct, e.g. _class => 'My::MarriedPerson'. Node will then be created using:

 My::MarriedPerson->new(name => 'Andi', age => 64)

If your constructor method name is not new, you can set that using the _constructor key.

If your constructor does not accept a list of attribute name and value pairs, but a hash(ref) of attributes, you can set _pass_attributes to hashref, and then node will be created using:

 My::Person->new({ name => 'Andi', age => 64 })

Or, if your constructor doesn't take any argument and the attributes are set using individual accessor methods, you can set the _pass_attributes key to false and then node will be created using:

 do {
     my $node = My::Person->new;
     $node->name('Andi');
     $node->age(64);
     $node;
 }

Finally, if you need total customization for the constructor and initialization of your node, you can supply the key _instantiate instead. This should be a code that instantiate your node. The code will be passed ($class, \%attrs) and should return the newly created node. Example:

 _instantiate => sub {
     my ($class, $attrs) = @_;
     $class->create_person($attrs->{name}, $attrs->{age} // 0);
 }

The _children key (arrayref of structs) instructs how to create children nodes. This will recursively call new_from_struct for each child. The parent's _constructor, _pass_attributes, and _instantiate keys will be set as the default for the child's struct, but of course child can override it should they want to.

Finally, the children will be connected to their parents and vice versa. And the final tree object (root node) is returned.

Continuing from the previous example:

 my $family_tree = My::Person->new_from_struct({
     name => 'Andi', age => 64, _children => [
         {name => 'Budi', age => 30},
         {name => 'Cinta', _class => 'My::MarriedPerson', _children => [
              {name => 'Deni'},
              {name => 'Eno'},
          ]},
     ]});

Here are the steps that will be performed (so in essence what new_from_struct provides is convenience of not having to connect parent and children nodes manually):

 my $andi = My::Person->new(name => 'Andi', age => 64);

 my $budi  = My::Person->new(name => 'Budi', age => 30);
 $budi->parent($andi);

 my $cinta = My::MarriedPerson->new(name => 'Cinta');
 $cinta->parent($andi);

 $andi->children([$budi, $cinta]);

 # class defaults back to My::Person since _class is not specified and not
 # passed down to children's struct

 my $deni = My::Person->new(name => 'Deni');
 $deni->parent($cinta);

 my $eno = My::Person->new(name => 'Eno');
 $eno->parent($cinta);

 $cinta->children([$deni, $eno]);

 $andi;

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/RoleBundle-TinyCommons-Tree.

SOURCE

Source repository is at https://github.com/perlancar/perl-RoleBundle-TinyCommons-Tree.

SEE ALSO

Code::Includable::Tree::FromStruct if you want to use the routines in this module without consuming a role.

Role::TinyCommons::Tree::FromObjArray if you want to build a tree of objects from a nested array of objects.

Role::TinyCommons::Tree::Node

Role::TinyCommons

AUTHOR

perlancar <perlancar@cpan.org>

CONTRIBUTING

To contribute, you can send patches by email/via RT, or send pull requests on GitHub.

Most of the time, you don't need to build the distribution yourself. You can simply modify the code, then test via:

 % prove -l

If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla plugin and/or Pod::Weaver::Plugin. Any additional steps required beyond that are considered a bug and can be reported to me.

COPYRIGHT AND LICENSE

This software is copyright (c) 2021, 2020, 2016 by perlancar <perlancar@cpan.org>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=RoleBundle-TinyCommons-Tree

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.