With all of the focus on OOP and frameworks, sometimes the utilities get ignored. These modules provide us with lightweight, simple, effective solutions to everyday problems, saving us all from reinventing the wheel. This talk looks at a several of the utilities and shows some of the less common ways they can save a lot of time.
The Codex of Business Writing Software for Real-World Solutions 2.pptx
Wheels we didn't re-invent: Perl's Utility Modules
1. Lazyness, Impatienence, and Hubris:
Getting there on wheels we didn’t re-invent.
Steven Lembark
Workhorse Computing
lembark@wrkhors.com
2. True Lazyness is what ain’t.
Not banging your head against a wall.
Especially one that someone else has padded.
Don’t re-invent the wheel.
Don’t maintain someone else’s code.
Don’t correct your mistakes with 20/20 hindsight.
3. The utility of lazyness
“Utility” modules:
Simple
Lightweight
No configuration.
Avoid side effects.
4. The utility of impatience
Many use XS.
Faster, cleaner, simpler code.
7. The original idea behind Scalar::Util:
Scalar::Util contains a selection of subroutines
that people have expressed would be nice to have in
the perl core, but the usage would not really be
high enough to warrant the use of a keyword, and
the size would be so small that being individual
extensions would be wasteful.
Graham Barr
15. using refaddr
Each object has a unique address.
say refaddr []; ’94141673084392’
say refaddr []; ’94141673084413’
16. using refaddr
Object-specific data by address:
sub inside_out_data
{
state $cache = {};
my $obj = shift;
my $data = $cache{ refaddr $obj } //= {};
...
}
17. using refaddr
Inside of inside-out objects:
sub inside_out_data
{
state $cache = {};
my $obj = shift;
my $data = $cache{ refaddr $obj } //= {};
...
}
30. List::Util
Has grown over time
reduce reductions any all
none notall first max maxstr
min minstr product sum sum0
pairs unpairs pairkeys pairvalues
pairgrep pairfirst pairmap
shuffle sample uniq uniqint
uniqnum uniqstr head tail
zip mesh
31. List::Util
List reduction
reduce reductions any all
none notall first max maxstr
min minstr product sum sum0
pairs unpairs pairkeys pairvalues
pairgrep pairfirst pairmap
shuffle sample uniq uniqint
uniqnum uniqstr head tail
zip mesh
32. List::Util
Key/Value & Pairs
reduce reductions any all
none notall first max maxstr
min minstr product sum sum0
pairs unpairs pairkeys pairvalues
pairgrep pairfirst pairmap
shuffle sample uniq uniqint
uniqnum uniqstr head tail
zip mesh
33. List::Util
Misc list
reduce reductions any all
none notall first max maxstr
min minstr product sum sum0
pairs unpairs pairkeys pairvalues
pairgrep pairfirst pairmap
shuffle sample uniq uniqint
uniqnum uniqstr head tail
zip mesh
37. Reducing your workload.
use List::Util qw( reduce );
use File::Spec::Functions qw( catdir splitdir );
sub mkdir_p
{
my $dir = shift;
reduce
{
use autodie qw( mkdir );
$a = catdir $a, $b;
-d $a || mkdir $a;
$a
} ( ‘’, splitdir $dir )
}
38. Reducing your workload.
use List::Util qw( reduce );
use File::Spec::Functions qw( catdir splitdir );
sub mkdir_p
{
my $dir = shift;
reduce
{
use autodie qw( mkdir );
$a = catdir $a, $b;
-d $a || mkdir $a;
$a
} ( ‘’, splitdir $dir )
}
39. Reducing your workload.
use List::Util qw( reduce );
use File::Spec::Functions qw( catdir splitdir );
sub mkdir_p
{
my $dir = shift;
reduce
{
use autodie qw( mkdir );
$a = catdir $a, $b;
-d $a || mkdir $a;
$a
} ( ‘’, splitdir $dir )
}
40. Reducing your workload.
use List::Util qw( reduce );
use File::Spec::Functions qw( catdir splitdir );
sub mkdir_p
{
my $dir = shift;
reduce
{
use autodie qw( mkdir );
$a = catdir $a, $b;
-d $a || mkdir $a;
$a
} ( ‘’, splitdir $dir )
}
41. reductions returns all results
use List::Util qw( reductions );
use File::Spec::Functions qw( catdir splitdir );
sub mkdir_p
{
use autodie qw( mkdir );
-d || mkdir
for reductions { catdir $a, $b }
( ‘’, splitdir $_[0] )
}
42. Easy to combine
Lack of side-effects:
reduce + splitdir + catdir.
Easy to mix and match due.
Useful design principle.
43. Unique list in input order
Different than extracting hash keys.
Hash keys have random order.
uniq preserves input order.
Useful for exterally sorted data:
uniq map { … } @input_data;
44. Unique list in input order
Comparison types:
uniq
uniqint
uniqnum
uniqstr
45. Do the Perly Shuffle
Non-destructive selection without replacement:
my @random_order = shuffle @input;
my @random_subset = sample $count => @input;
46. Pair op’s derived from Raku
Pair = [ key => value ].
Raku hash == list of pairs.
pairgrep
Compares key & value from list.
unpairs
Flattens pairs into list.
47. Search keys & values in one pass
$a is a key, $b is a value.
Compare key or value without separating them.
my %subset
= pairgrep
{
$a # key
$b # value
}
%bighash;
48. Search keys & values in one pass
Reeeeellly nice for filtering hash values!
my %subset
= pairgrep
{
$b % 2
}
%bighash;
49. Heads I win...
Simple list operations:
head( N ) == first N elements
head( -N ) == all but last n elemens.
tail( N ) == last N items from list.
tail( -N ) == all but last N items.
50. Simple things done easily
Simple fix for an obvious step:
Build a hash from keys and values.
my %hash = zip @keyz, @valz;
51. But wait! There’s more!!!
Junctions
Treatment of an empty list
all BLOCK LIST
all_u BLOCK LIST
any BLOCK LIST
any_u BLOCK LIST
none BLOCK LIST
none_u BLOCK LIST
notall BLOCK LIST
notall_u BLOCK LIST
one BLOCK LIST
one_u BLOCK LIST
Transformation
apply BLOCK LIST
insert_after BLOCK VALUE LIST
insert_after_string STRING VALUE LIST
pairwise BLOCK ARRAY1 ARRAY2
mesh ARRAY1 ARRAY2 [ ARRAY3 ... ]
zip ARRAY1 ARRAY2 [ ARRAY3 ... ]
zip6
zip_unflatten
listcmp ARRAY0 ARRAY1 [ ARRAY2 ... ]
arrayify LIST[,LIST[,LIST...]]
uniq LIST
distinct LIST
singleton LIST
duplicates LIST
frequency LIST
occurrences LIST
mode LIST
slide BLOCK LIST
Partitioning
after BLOCK LIST
after_incl BLOCK LIST
before BLOCK LIST
before_incl BLOCK LIST
part BLOCK LIST
samples COUNT LIST
Iteration
each_array ARRAY1 ARRAY2 ...
each_arrayref LIST
natatime EXPR, LIST
slideatatime STEP, WINDOW, LIST
Searching
firstval BLOCK LIST
first_value BLOCK LIST
onlyval BLOCK LIST
only_value BLOCK LIST
lastval BLOCK LIST
last_value BLOCK LIST
firstres BLOCK LIST
first_result BLOCK LIST
onlyres BLOCK LIST
only_result BLOCK LIST
lastres BLOCK LIST
last_result BLOCK LIST
indexes BLOCK LIST
firstidx BLOCK LIST
first_index BLOCK LIST
onlyidx BLOCK LIST
only_index BLOCK LIST
lastidx BLOCK LIST
last_index BLOCK LIST
Sorting
sort_by BLOCK LIST
nsort_by BLOCK LIST
qsort BLOCK ARRAY
Searching in sorted Lists
bsearch BLOCK LIST
bsearchidx BLOCK LIST
bsearch_index BLOCK LIST
lower_bound BLOCK LIST
upper_bound BLOCK LIST
equal_range BLOCK LIST
Operations on sorted Lists
binsert BLOCK ITEM LIST
bsearch_insert BLOCK ITEM LIST
bremove BLOCK LIST
bsearch_remove BLOCK LIST
Counting and calculation
true BLOCK LIST
false BLOCK LIST
reduce_0 BLOCK LIST
reduce_1 BLOCK LIST
reduce_u BLOCK LIST
minmax LIST
minmaxstr LIST
52. List::MoreUtils
Junctions
Treatment of an empty list
all BLOCK LIST
all_u BLOCK LIST
any BLOCK LIST
any_u BLOCK LIST
none BLOCK LIST
none_u BLOCK LIST
notall BLOCK LIST
notall_u BLOCK LIST
one BLOCK LIST
one_u BLOCK LIST
Transformation
apply BLOCK LIST
insert_after BLOCK VALUE LIST
insert_after_string STRING VALUE LIST
pairwise BLOCK ARRAY1 ARRAY2
mesh ARRAY1 ARRAY2 [ ARRAY3 ... ]
zip ARRAY1 ARRAY2 [ ARRAY3 ... ]
zip6
zip_unflatten
listcmp ARRAY0 ARRAY1 [ ARRAY2 ... ]
arrayify LIST[,LIST[,LIST...]]
uniq LIST
distinct LIST
singleton LIST
duplicates LIST
frequency LIST
occurrences LIST
mode LIST
slide BLOCK LIST
Partitioning
after BLOCK LIST
after_incl BLOCK LIST
before BLOCK LIST
before_incl BLOCK LIST
part BLOCK LIST
samples COUNT LIST
Iteration
each_array ARRAY1 ARRAY2 ...
each_arrayref LIST
natatime EXPR, LIST
slideatatime STEP, WINDOW, LIST
Searching
firstval BLOCK LIST
first_value BLOCK LIST
onlyval BLOCK LIST
only_value BLOCK LIST
lastval BLOCK LIST
last_value BLOCK LIST
firstres BLOCK LIST
first_result BLOCK LIST
onlyres BLOCK LIST
only_result BLOCK LIST
lastres BLOCK LIST
last_result BLOCK LIST
indexes BLOCK LIST
firstidx BLOCK LIST
first_index BLOCK LIST
onlyidx BLOCK LIST
only_index BLOCK LIST
lastidx BLOCK LIST
last_index BLOCK LIST
Sorting
sort_by BLOCK LIST
nsort_by BLOCK LIST
qsort BLOCK ARRAY
Searching in sorted Lists
bsearch BLOCK LIST
bsearchidx BLOCK LIST
bsearch_index BLOCK LIST
lower_bound BLOCK LIST
upper_bound BLOCK LIST
equal_range BLOCK LIST
Operations on sorted Lists
binsert BLOCK ITEM LIST
bsearch_insert BLOCK ITEM LIST
bremove BLOCK LIST
bsearch_remove BLOCK LIST
Counting and calculation
true BLOCK LIST
false BLOCK LIST
reduce_0 BLOCK LIST
reduce_1 BLOCK LIST
reduce_u BLOCK LIST
minmax LIST
minmaxstr LIST