Perl Sq: Seq in combination with I/O
In one of my programs I already use my module. This program creates a new test-file in the ’t’ folder from a template. From all files in that directory I want to automatically pick the next highest number. I don’t want to search for the number myself.
So here is how i read all files from disk and only pick files matching the pattern “%d-$title.t”. Then i want the maximum number.
This example shows how you can “connect” to other modules to use them. In this example
its Path::Tiny
.
|
|
Here is how it works.
- It begins with
max
. max
wants to know the highest numerical value. So he askchoose
for the next value.choose
also don’t know abbout any value, he askmap
to give him one.map
also don’t know about any value, so he askwrap
about one.wrap
finally knows about a value. He gives him the next one, and asks Do you want this?map
looks at it. He says, yes i take all. Then he askschoose
is this the basename you wanted?choose
looks at it. He runs a regex on it to proof the correct format, and extract the number from the basename.- When it is the correct format, he gives
max
the requested file. (goto #8) - When it not the correct format, he throws it away, and asks
map
again for the next value. (goto #4)
- When it is the correct format, he gives
max
stores the first value as the maximum value. Then he ask again for the next value (goto #2). He continues as longchoose
returns an item itself. Andchoose
continues as long he gets one frommap
and so on …- When
choose
does not return a value anymore.max
returns the maximum value he stored so far. Whenchoose
does not give him a single value. He choose0
as the default to return.
So max
starts the evaluation. It bubbles back to wrap
. So execution is basically
written in reverse. In the case of max
all items must be scanned.
There could be multiple different ways to optimze its performance. But, you
probably always will start with replacing/optimizing wrap
.
When you give wrap
all items at once it internally creates an array and serves
all request from it. This is the operation that blocks. But only once, and at the
very beginning.
Theoretically there is only one way to fix it. You just give it a function that works like a sequence. You can pass it any function that returns another function.
This is how the internals of sequence works. But there are multiple different helpers (Constructors) to help you create such an construct.
Throughout the system, undef
is used like an optional. When you return it,
its considered the end of the iterator. Or in some functions returning undef
means = skip this item. So undef
values basically disappear as long you use
Seq
.
Here a funny part. Seq
can return undef
. It’s like talking with others.
Inside Seq
there is no undef
. But it returns it, just like it keeps getting one
from the outside itself.
Like max
that can return an undef
when the sequence not only contains a single
value. Luckily max
can be given a default value that in that case is returned
instead of an undef
.
So I am basically fixing “The multi-millard dollar-bug”. Everything as a Perl module to load.
Or at least, an attempt.