NAME
Lazy::Util - Perl utilities for lazy evaluation
VERSION
version 0.001
SYNOPSIS
use Lazy::Util qw/ l_grep l_map /;
my $lazy = l_map { $_ * 2 } l_grep { /^[0-9]+$/ } 3, 4, 5, sub {
print "Enter a number: ";
return scalar readline(STDIN);
};
while (defined(my $answer = $lazy->get())) {
print "Double your number: $answer\n";
}
DESCRIPTION
Perl utility functions for lazy evalutation.
FUNCTIONS
This module has two sets of functions, the l_*
functions and the g_*
functions. The l_*
functions are designed to return a Lazy::Util
object which you can get values from, the g_*
functions are designed to get a value out of a Lazy::Util
object. Some of the g_*
functions may never return if the source of values is infinite, but they are for the most part designed to not eat up all of your memory at least ;).
All these functions can be exported, but none are exported by default. You can use the :all
export tag to export all of them.
l_*
functions
The l_*
functions are:
l_concat - l_concat(@sources)
my $lazy = l_concat @sources;
l_concat
returns a Lazy::Util
object which will simply return each subsequent value from the list of sources it's given.
l_first - l_first($n, @sources)
my $lazy = l_first $n, @sources;
l_first
will return a Lazy::Util
object which will only get the first $n
values from the subsequent arguments. This can be used the 'break' an otherwise infinite list to only return a certain number of results.
l_grep - l_grep($code, @sources)
my $lazy = l_grep { ... } @sources;
l_grep
will return a Lazy::Util
object which will filter out any value which doesn't return true from the $code
block in the first argument.
l_map - l_map($code, @sources)
my $lazy = l_map { ... } @sources;
l_map
will return a Lazy::Util
object which will transform any value using the $code
block in the first argument.
l_nuniq - l_nuniq(@sources)
my $lazy = l_nuniq @sources;
l_nuniq
will return a Lazy::Util
object which will only return numerically unique values from the sources. This has the potential to consume all of your memory if the @sources
are infinite.
l_uniq - l_uniq(@sources)
my $lazy = l_uniq @sources;
l_uniq
will return a Lazy::Util
object which will only return unique values from the sources. This has the potential to consume all of your memory if the @sources
are infinite.
l_until l_until($code, @sources)
my $lazy = l_until { ... } @sources;
l_until
will return a Lazy::Util
object which will return values from the @sources
until the $code
block returns true, after which it will be exhausted.
g_*
functions
The g_*
functions are:
g_count - g_count(@sources)
my $count = g_count @sources;
g_count
counts the number of values from the @sources
and returns how many there were. This has the potential to never return if given a source of infinite values.
g_first - g_first(@sources)
my $val = g_first @sources;
g_first
returns the first value from the list of arguments, lazily evaluating them. Equivalent to l_concat(...)->get();
. If @sources
is empty, it will return undef
.
g_join - g_join($sep, @sources)
my $lines = g_join $str, @sources;
g_join
evaluates all the values it's given and returns them joined into a string. This has the potential to never return as well as running out of memory if given a source of infinite values. If @sources
is empty, it will return undef
.
g_last - g_last(@sources)
my $val = g_last @sources;
g_last
evaluates all the values it's given and returns the last value. This has the potential to never return if given a source of infinite values. If @sources
is empty, it will return undef
.
g_max - g_max(@sources)
my $val = g_max @sources;
g_max
evaluates all the values it's given and returns the highest one. This has the potential to never return if given a source of infinite values. If @sources
is empty, it will return undef
.
g_min - g_min(@sources)
my $val = g_min @sources;
g_min
evaluates all the values it's given and returns the lowest one. This has the potential to never return if given a source of infinite values. If @sources
is empty, it will return undef
.
g_prod - g_prod(@sources)
my $val = g_prod @sources;
g_prod
evaluates all the values it's given and returns the product of all of them. This has the potential to never return if given a source of infinite values. Unless one of them is 0. If so, it will short-circuit and return 0. If @sources
is empty, it will return 1
.
g_sum - g_sum(@sources)
my $val = g_sum @sources;
g_sum
evaluates all the values it's given and returns the sum of all of them. This has the potential to never return if given a source of infinite values. If @sources
is empty, it will return 0
.
@sources
The @sources
array that most (all?) of these functions take can be any combination of regular scalar values, Lazy::Util
objects, Scalar::Defer variables (see "NOTES"), or subroutine references. Each of these will be iterated through from start to finish, and if one of them returns undef
, the next one will be used instead, until the last one returns undef
.
For instance, in the following scenario:
my @values = qw/ a b c /;
my $source = sub { shift @values };
my $lazy = l_concat $source, 1;
my @results = ($lazy->get(), $lazy->get(), $lazy->get(), $lazy->get());
What happens when you run $lazy->get()
the first time is that the subroutine in $source
will be executed, and so @values
will change to only contain qw/ b c /
, and a
will be returned. The next time @values
will be changed to only contain qw/ c /
, and b
will be returned. The third $lazy->get()
will change @values
to qw//
(an empty array), and return the c
.
So far so good.
What happens with the next $lazy->get()
is that the subroutine in $source
will be executed one last time, and it will run shift @values
, but @values
is empty, so it will return undef
, which will signal that $source
is exhausted, and so it will be discarded. The next value will be taken from the next element in @sources
, which is the single scalar 1
.
This means that at the end, @results
will contain qw/ a b c 1 /
, and any subsequent call to $lazy->get()
will return undef
.
Lazy::Util objects
Lazy::Util
objects encapsulate a set of lazy evaluation functions, meaning you can combine them using the l*
functions listed above.
new - Lazy::Util->new($source)
my $lazy = Lazy::Util->new(sub { $i++ });
Lazy::Util->new
takes a code reference which will be used as the source for all the values and returns a Lazy::Util
object encapsulating that source.
exhausted - $lazy->exhausted()
my $exhausted = $lazy->exhausted();
$lazy->exhausted()
checks if there's any more values left in the source, and caches any such value for the next $lazy->get()
call. It returns 0 if there are values left, and 1 if the source is exhausted.
An exhausted Lazy::Util
object will always return undef
from a $lazy->get()
call.
get - $lazy->get()
my $next = $lazy->get();
$lazy->get
returns the next value from the source it encapsulates. When there are no more values it returns undef
.
get_all - $lazy->get_all()
my @crazy = $lazy->get_all();
$lazy->get_all
returns all the values from the source, if it can. This has the potential to never return as well as running out of memory if given a source of infinite values.
NOTES
If Scalar::Defer is installed, it will assume that any variable of type 0
is a Scalar::Defer
variable and will treat it as a source of values.
Not to be confused with Lazy::Utils.
SEE ALSO
AUTHOR
Andreas Guldstrand <andreas.guldstrand@gmail.com>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2017 by Andreas Guldstrand.
This is free software, licensed under:
The MIT (X11) License