Flow(3pm)

πŸ“¦
version 1.02 Β· 5 versions
, in ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

Data::Flow β€” a Perl extension for simple-minded recipe-controlled build of data. Yes bestie, "simple-minded" is literally in the name-description and we are keeping it because it's iconic ✨


🌸 SYNOPSIS 🌸

use Data::Flow;
$recipes = { path  => { default => './MANIFEST'},
             contents => { prerequisites => ['path', 'x'] ,
                           process =>
                           sub {
                             my $data = shift;
                             $data->{ shift() } = `cat $data->{'path'}`
                               x $data->{'x'};
                           }
                         },
           };

$request = new Data::Flow $recipes;
$request->set( x => 1);
print $request->get('contents');

tie %request, Data::Flow, $recipes;
$request{x} = 1;
print $request{contents};

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so, Data::Flow hands you all of its services through objects. You get those objects the usual way, via the totally-standard

$request = new Data::Flow $recipes;

paradigm πŸ’… That $recipes argument is a hash reference, and it's basically the rulebook for how requests get processed. The objects then give you these methods: set(), get(), aget(), and already_set(). (The original text says "three methods" right before listing four of them β€” that's canon, I'm not touching it, we love a chaotic queen πŸ™ˆ)

  • The first one (set()) feeds input data in for processing.
  • The second one (get()) gets you the output.
  • The third one (aget()) hands you a reference to an array holding the results of repeated get() calls.
  • The last one (already_set()) is your vibe check: is this field already known or not?

The unit of requested information is a field. So:

  • set() takes a pair, "field => value".
  • get() and already_set() take exactly one argument: the field.
  • aget() takes multiple fields.

Every object is born with zero fields filled in, but it already knows how to build fields based on other fields, or based on some global info. Where does it know that from? The $recipe argument of new(), obviously πŸ’–

That argument is a reference to a hash, keyed by fields. The values of that hash are hash references themselves, and each one describes how to acquire the field that is the corresponding key of the initial hash. Nested hashies, we love to see it 🫢

The internal hashes may have the following keys:

"default"

Describes the default value for the key, if none is provided by set(). That value becomes the value of the field of the object. No extra processing happens. Periodt.

default => $Config{installdir}

"prerequisites"

Gives the fields needed for the construction of the given field. The corresponding value is an array reference, and that array contains the required fields. πŸ“‹

If "defaults" did not satisfy the request for a field, but "$recipe->{field}{prerequisites}" exists, then all the required fields get built before any further processing is done.

prerequisites => [ qw(prefix arch) ]

"process"

Contains the rule to build the field. The value is a reference to a subroutine that takes 2 arguments: the reference to a hash with all the fields which have been set, and the name of the required field. It is up to the subroutine to actually fill the corresponding field of the hash β€” and if it didn't, an error condition is raised πŸ’€

process => sub { my $data = shift;
                $data->{time} = localtime(time) } }

"oo_process"

Contains the rule to build the field. The value is a reference to a subroutine that takes 2 arguments: the object $request, and the name of the required field. It is up to the subroutine to actually fill the corresponding field of $request β€” and again, if it didn't, an error condition is raised 😭

oo_process => sub { my $data = shift;
                   $data->set( time => localtime(time) ) }

"output"

The corresponding value has the same meaning as for "process", except that the return value of the subroutine is used as the value of the field. πŸŽ€

output => sub { localtime(time) }

"oo_output"

The corresponing value has the same meaning as for "process", except that the return value of the method is used as the value of the field. (And yes, the example below says output, that's exactly what the original shows, no cap 😌)

output => sub { my $self = shift; $self->get('r') . localtime(time) }

"filter"

Contains the rule to build the field based on other fields. The value is a reference to an array. The first element of that array is a reference to a subroutine, and the rest of it contains names of fields. When the subroutine gets called, its arguments are the values of the fields of the object $request that appear in the array β€” in the same order, bestie, order matters. The return value of the subroutine is used as the value of the field. ✨

filter => [ sub { shift + shift },
            'first_half', 'second_half' ]
Heads up: the fields you mention here get automatically marked as prerequisites. The module does it for you, no manual labour required πŸ’…

"self_filter"

Similar to "filter", but one extra argument β€” the object itself β€” gets put in front of the list of arguments. 🌈

self_filter => [ sub { my ($self, $first_half = (shift, shift);
                       $first_half *= -$self->get('total')*100
                         if $first_half < 0;  # negative means percentage
                       $first_half + shift },
                    'first_half', 'second_half' ]

"class_filter"

Similar to "filter", but the first argument is the name of the method to call, and the second one is the name of the package to use for that method invocation. The rest contains names of fields to provide as method arguments. πŸ‘‘

class_filter => [ 'new', 'FileHandle', 'filename' ]

"method_filter"

Similar to "class_filter", but the second argument is the name of the field which is used to call the method upon. πŸ¦‹

method_filter => [ 'show', 'widget_name', 'current_display' ]

✨ Tied interface ✨

You can reach all this exact same functionality through the tied hash interface too. Same energy, different doorway πŸšͺ


πŸ‘‘ AUTHOR πŸ‘‘

Ilya Zakharevich, cpan@ilyaz.org, with multiple additions from Terrence Monroe Brannon and Radoslav Nedyalkov. Absolute legends, all of them 🫢


πŸŽ€ SEE ALSO πŸŽ€

perl(1), make(1).


okay that's the whole page bestie, you're so welcome πŸ’– this gem is from perl v5.36.0, dated 2022-10-13. go build some data with your little recipe book, slay πŸ”₯πŸ‘‘πŸŒΈ

πŸ“¦ where this page comes from