NAME
List::Gen - provides functions for generating lists
VERSION
version 0.30
SYNOPSIS
this module provides higher order functions, iterators, and other utility functions for working with lists. walk lists with any step size you want, create lazy ranges and arrays with a map like syntax that generate values on demand. there are several other hopefully useful functions, and all functions from List::Util are available.
use List::Gen;
print "@$_\n" for every 5 => 1 .. 15;
# 1 2 3 4 5
# 6 7 8 9 10
# 11 12 13 14 15
print mapn {"$_[0]: $_[1]\n"} 2 => %myhash;
for (range 0.345, -21.5, -0.5) {
# loops over 0.345, -0.155, -0.655, -1.155 ... -21.155
}
EXPORT
use List::Gen; # is the same as
use List::Gen qw/mapn by every range gen genr cache apply zip min max reduce/;
the following functions are available:
mapn by every range gen genr cache apply zip min max reduce d deref slide expand collect
from List::Util => first max maxstr min minstr reduce shuffle sum
FUNCTIONS
mapn CODE NUM LIST-
this function works like the builtin
mapbut takesNUMsized steps over the list, rather than one element at a time. inside theCODEblock, the current slice is in@_and$_is set to$_[0]. slice elements are aliases to the original list. ifmapnis called in void context, theCODEblock will be executed in void context for efficiency.print mapn {$_ % 2 ? "@_" : " [@_] "} 3 => 1..20; # 1 2 3 [4 5 6] 7 8 9 [10 11 12] 13 14 15 [16 17 18] 19 20 print "student grades: \n"; mapn { print shift, ": ", (reduce {$a + $b} @_)/@_, "\n"; } 5 => qw { bob 90 80 65 85 alice 75 95 70 100 eve 80 90 80 75 }; by NUM LISTevery NUM LIST-
byandeveryare exactly the same, and allow you to add variable step size to any other list control structure with whichever reads better to you.for (every 2 => @_) {do something with pairs in @$_} grep {do something with triples in @$_} by 3 => @list;the functions generate an array of array references to
NUMsized slices ofLIST. the elements in each slice are aliases to the original list.in list context, returns a real array. in scalar context, returns a generator.
my @slices = every 2 => 1 .. 10; # real array my $slices = every 2 => 1 .. 10; # generator for (every 2 => 1 .. 10) { ... } # real array for (@{every 2 => 1 .. 10}) { ... } # generatorif you plan to use all the slices, the real array is better. if you only need a few, the generator won't need to compute all of the other slices.
print "@$_\n" for every 3 => 1..9; # 1 2 3 # 4 5 6 # 7 8 9 my @a = 1 .. 10; for (every 2 => @a) { @$_[0, 1] = @$_[1, 0] # flip each pair } print "@a"; # 2 1 4 3 6 5 8 7 10 9 print "@$_\n" for grep {$$_[0] % 2} by 3 => 1 .. 9; # 1 2 3 # 7 8 9 apply {CODE} LIST-
apply a function that modifies
$_to a copy ofLISTand return the copyprint join ", " => apply {s/$/ one/} "this", "and that"; > this one, and that one zip LIST_of_ARRAYREF-
interleaves the passed in lists to create a new list.
zipcontinues until the end of the longest list,undefis returned for missing elements of shorter lists.%hash = zip [qw/a b c/], [1..3]; # same as %hash = (a => 1, b => 2, c => 3);
generators
in this document, generators will refer to tied arrays that generate their elements on demand. generators can be used as iterators in perl's list control structures such as for map or grep . since generators are lazy, infinite generators can be created. slow generators can also be cached
all generator functions, in scalar context, will return a reference to a tied array. elements are created on demand as they are dereferenced.
my $range = range 0, 1_000_000, 0.2; # will produce 0.0, 0.2, 0.4, ... 1000000.0
say map sprintf('% -5s', $_)=> @$range[10 .. 15]; # calculates 5 values from $range
my $gen = genr {$_**2} $range; # attaches a generator function to a range
say map sprintf('% -5s', $_)=> @$gen[10 .. 15];
>> 2 2.2 2.4 2.6 2.8 3
>> 4 4.84 5.76 6.76 7.84 9
the returned reference also has the following methods:
$gen->() # ->next() style iterator
$gen->more # test if $gen->() not past end
$gen->reset # reset $gen->() to 0
$gen->reset(4) # next $gen->() returns $$gen[4]
$gen->(index) # returns $$gen[index]
$gen->get(index) # same
$gen->(4 .. 12) # returns @$gen[4 .. 12]
$gen->slice(4 .. 12) # same
$gen->size # returns scalar @$gen
direct access through dereferencing the array is usually clearer and faster. the methods are only necessary when working with indicies outside of perl's limit (0 .. 2**31 - 1). or when fetching a list return value (perl clamps the return to a scalar with the array syntax).
some generator functions such as range, in list context, return the actual tied array. it only makes sense to use this syntax directly in list control structures, otherwise all elements will be generated during the first copy. the real tied array also does not have the above accessor methods.
range START STOP [STEP]-
returns a generator for values from
STARTtoSTOPbySTEP, inclusive.STEPdefaults to 1 but can be fractional and negative. depending on your choice ofSTEP, the last value returned may not always beSTOP.range(0, 3, 0.4) returns (0, 0.4, 0.8, 1.2, 1.6, 2, 2.4, 2.8)in list context, returns a generator array (see warning above). in scalar context, returns a generator reference (usually what you want). to obtain a real array, simply assign a range to an
ARRAYvariable.print "$_ " for range 0, 1, 0.1; # 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 print "$_ " for range 5, 0, -1; # 5 4 3 2 1 0 my $nums = range 0, 1_000_000, 2; print "@$nums[10, 100, 1000]"; # gets the tenth, hundredth, and thousandth numbers in the range # without calculating any other valuessince the returned generator uses lazy evaluation, even gigantic ranges are created instantly, and take little space. however, when used directly in a for loop, perl seems to preallocate space for the array anyway. for reasonably sized ranges this is unnoticeable, but for huge ranges, avoiding the problem is as simple as wrapping the range with
@{ }for (@{range 2**30, -2**30, -1.3}) { # the loop will start immediately without eating all # your memory, and hopefully you will exit the loop early } gen CODE LISTgenr CODE GENERATORgenr CODE START STOP [STEP]-
genis a lazy version ofmapwhich attaches a code block to a list. it returns a generator that will apply the code block on demand.genrworks the same way, except it takes a generator, or suitable arguments forrange. with no arguments,genruses the range 0 .. infinitynote that there is overhead involved with lazy generation. simply replacing all calls to
mapwithgenwill almost certainly slow down your code. usegenin situations where the time / memory required to completely generate the list is unacceptable.the return semantics are the same as
range.my @result = map {slow_function($_)} @source; # slow function called @source times my $result = gen {slow_function($_)} @source; # slow function not called my ($x, $y) = @$result[4, 7]; # slow function called twice my $lazy = genr {slow_function($_)} 1, 1_000_000_000; print $$lazy[1_000_000]; # slow_function only called once cache GENERATORcache CODEcache list =CODE>-
cachewill return a cached version of the generator returned by functions in this package. when passed a code reference, cache returns a memoized code ref (arguments joined with$;). when in 'list' mode, CODE is executed in list context, otherwise scalar context is used.my $gen = cache gen {slow($_)} @source; print $gen->[123]; # slow called once ... print @$gen[123, 456] # slow called once expand GENERATORexpand SCALE GENERATOR-
expandscales a generator with with elements that return equal sized lists. can be passed a list length, or will automatically determine it from the length of the list returned by the first element of the generator.expandimplicitly caches its returned generator.my $multigen = genr {$_, $_/2, $_/4} 1, 10; # each element returns a list say join ' '=> $$multigen[0]; # 0.25 # only last element say join ' '=> $multigen->(0); # 1 0.5 0.25 # works say scalar @$multigen; # 10 say $multigen->size; # 10 my $expanded = expand $multigen; say join ' '=> @$expanded[0 .. 2]; # 1 0.5 0.25 say join ' '=> $expanded->(0 .. 2); # 1 0.5 0.25 say scalar @$expanded; # 30 say $expanded->size; # 30 my $expanded = expand genr {$_, $_/2, $_/4} 1, 10; # in one line collect SCALE GENERATOR-
collectis the inverse ofexpand dd SCALARderefderef SCALAR-
dereference a
SCALAR,ARRAY, orHASHreference. any other value is returned unchangedprint join " " => map deref, 1, [2, 3, 4], \5, {6 => 7}, 8, 9, 10; # prints 1 2 3 4 5 6 7 8 9 10 slide {CODE} WINDOW LIST-
slides a
WINDOWsized slice overLIST, callingCODEfor each slice and collecting the resultas the window reaches the end, the passed in slice will shrink
print slide {"@_\n"} 2 => 1 .. 4 # 1 2 # 2 3 # 3 4 # 4 # only one element here
AUTHOR
Eric Strom, <ejstrom at gmail.com>
BUGS
please report any bugs or feature requests to bug-list-functional at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=List-Functional. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
COPYRIGHT & LICENSE
copyright 2009 Eric Strom.
this program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
see http://dev.perl.org/licenses/ for more information.