Perl's Functional Functions
The common (core) ones...
● Built-in:
– grep – Filters a list.
– map – Creates or transforms a list.
– sort – Sorts a list.
● List::Util (core)
– first – Like grep, but returns first one found.
– reduce – Summarizes a list.
The common CPAN ones:
● List::MoreUtils
– any – Return true if any element in list matches.
– all – Return true if all elements match.
– pairwise – Transform two lists, pairwise, into one.
– Many others!
Filtering a list
my @odds;
foreach ( qw( a b c d e ) ) {
push @filtered, $_
if ord( $_ ) % 2;
}
say for @odds;
Filtering a list with grep
my @odds;
foreach (
qw( a b c d e )
) {
push @odds, $_
if ord( $_ ) % 2;
}
say for @odds;
my @odds = grep {
ord( $_ ) % 2
} qw( a b c d e );
say for @odds;
my @odds = grep { ord($_) % 2 } qw( a b c d e );
Which indices contain odd ords?
my @chars = qw( a c f b q r n b d );
my @odds_by_idx = grep {
ord( $chars[$_] ) % 2
} 0 .. $#chars;
grep
● list_b = grep { code block } ( list_a )
● Inside code block, $_ is it.
● If code block's return value is true, $_ is appended to
list_b.
● As with foreach, $_ is an alias.
● list_b and list_a need not be arrays.
● Simple expressions may be used in place of code
block.
Simple expressions in place of code
block
@explosions = grep { /bkaboomb/i } @phrases;
@explosions = grep /bkaboomb/i, @phrases;
@ones = grep { $_ == 1 } @booleans;
@ones = grep $_ == 1, @booleans;
● If it can't be expressed as a simple expression,
use a code block.
● Expression form requires a comma.
Transforming a list
sub chars_to_ords {
my @ords;
foreach ( @_ ) {
push @ords, ord $_;
}
return @ords;
}
my @ord_vals = chars_to_ords( qw( a b c d e ) );
Transforming a list with map
sub chars_to_ords {
my @ords;
foreach ( @_ ) {
push @ords, ord $_;
}
return @ords;
}
my @ordinals
= chars_to_ords(
qw( a b c d e )
);
my @ordinals
= map { ord $_ }
qw( a b c d e );
my @ordinals = map { ord $_ } qw( a b c d e );
Lists don't have to be arrays
say for map { ord } qw( a b c d e );
map
● list_b = map { code block } ( list_a )
● Inside code block, $_ is it.
● code block's return value is appended to list_b.
● As with foreach, $_ is an alias.
● list_b and list_a need not be arrays.
● code block is a subroutine; no last, no next.
● Skip current iteration by returning an empty list.
Simple expressions don't require
code blocks.
say for map ord, qw( a b c d e );
# The expression form requires a comma.
Chaining is legal (even encouraged)
say for
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, ord fc $_ ] }
qw( a b c d e );
# The Schwartzian Transform.
Sort?
@sorted = sort @unsorted;
@sorted = sort { $a <=> $b } @unsorted; # Ascend, numeric
@sorted = sort { $b <=> $a } @unsorted; # Descend, numeric
@sorted = sort { $a cmp $b } @unsorted; # Ascend, stringy
@sorted = sort {
$a <=> $b || $a cmp $b
} @unsorted; # Ascending numeric, then stringy.
@sorted
= sort { $a->{name} cmp $b->{name} } @unsorted;
List::Util
$first_one = first { /^kaboomb/i } @haystack;
$sum = reduce { $a + $b } @numbers;
$max = reduce { $a > $b ? $a : $b } @numbers;
List::MoreUtils
$has_quiche = any { /bquicheb/ } @foods; # T/F
$all_unicorns
= all { $_ eq 'unicorn' } @animals; # T/F
@joint_incomes = pairwise { $a + $b } @his, @hers;
@evens_odds = part { $_ % 2 } 1 .. 9; # LOLs
List::MoreUtils “natatime”
my @alphabet = ( 'a' .. 'z' );
my $iterator = natatime 3, @alphabet;
while( my @chars = $iterator->() ) {
print “@charsn”;
}
__END__
a b c
d e f
…
y z
List::MoreUtils
● Too many to mention them all.
– See https://metacpan.org/module/List::MoreUtils
Resources
● perldoc -f grep
● perldoc -f map
● perldoc -f sort
● perldoc List::Util
● https://metacpan.org/module/List::MoreUtils
Salt Lake Perl Mongers
http://saltlake.pm.org
Slides on slideshare.net
http://www.slideshare.net/daoswald/perls-functional-functions
Dave Oswald
davido@cpan.org

Perls Functional functions

  • 1.
  • 2.
    The common (core)ones... ● Built-in: – grep – Filters a list. – map – Creates or transforms a list. – sort – Sorts a list. ● List::Util (core) – first – Like grep, but returns first one found. – reduce – Summarizes a list.
  • 3.
    The common CPANones: ● List::MoreUtils – any – Return true if any element in list matches. – all – Return true if all elements match. – pairwise – Transform two lists, pairwise, into one. – Many others!
  • 4.
    Filtering a list my@odds; foreach ( qw( a b c d e ) ) { push @filtered, $_ if ord( $_ ) % 2; } say for @odds;
  • 5.
    Filtering a listwith grep my @odds; foreach ( qw( a b c d e ) ) { push @odds, $_ if ord( $_ ) % 2; } say for @odds; my @odds = grep { ord( $_ ) % 2 } qw( a b c d e ); say for @odds;
  • 6.
    my @odds =grep { ord($_) % 2 } qw( a b c d e );
  • 7.
    Which indices containodd ords? my @chars = qw( a c f b q r n b d ); my @odds_by_idx = grep { ord( $chars[$_] ) % 2 } 0 .. $#chars;
  • 8.
    grep ● list_b =grep { code block } ( list_a ) ● Inside code block, $_ is it. ● If code block's return value is true, $_ is appended to list_b. ● As with foreach, $_ is an alias. ● list_b and list_a need not be arrays. ● Simple expressions may be used in place of code block.
  • 9.
    Simple expressions inplace of code block @explosions = grep { /bkaboomb/i } @phrases; @explosions = grep /bkaboomb/i, @phrases; @ones = grep { $_ == 1 } @booleans; @ones = grep $_ == 1, @booleans; ● If it can't be expressed as a simple expression, use a code block. ● Expression form requires a comma.
  • 10.
    Transforming a list subchars_to_ords { my @ords; foreach ( @_ ) { push @ords, ord $_; } return @ords; } my @ord_vals = chars_to_ords( qw( a b c d e ) );
  • 11.
    Transforming a listwith map sub chars_to_ords { my @ords; foreach ( @_ ) { push @ords, ord $_; } return @ords; } my @ordinals = chars_to_ords( qw( a b c d e ) ); my @ordinals = map { ord $_ } qw( a b c d e );
  • 12.
    my @ordinals =map { ord $_ } qw( a b c d e );
  • 13.
    Lists don't haveto be arrays say for map { ord } qw( a b c d e );
  • 14.
    map ● list_b =map { code block } ( list_a ) ● Inside code block, $_ is it. ● code block's return value is appended to list_b. ● As with foreach, $_ is an alias. ● list_b and list_a need not be arrays. ● code block is a subroutine; no last, no next. ● Skip current iteration by returning an empty list.
  • 15.
    Simple expressions don'trequire code blocks. say for map ord, qw( a b c d e ); # The expression form requires a comma.
  • 16.
    Chaining is legal(even encouraged) say for map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, ord fc $_ ] } qw( a b c d e ); # The Schwartzian Transform.
  • 17.
    Sort? @sorted = sort@unsorted; @sorted = sort { $a <=> $b } @unsorted; # Ascend, numeric @sorted = sort { $b <=> $a } @unsorted; # Descend, numeric @sorted = sort { $a cmp $b } @unsorted; # Ascend, stringy @sorted = sort { $a <=> $b || $a cmp $b } @unsorted; # Ascending numeric, then stringy. @sorted = sort { $a->{name} cmp $b->{name} } @unsorted;
  • 18.
    List::Util $first_one = first{ /^kaboomb/i } @haystack; $sum = reduce { $a + $b } @numbers; $max = reduce { $a > $b ? $a : $b } @numbers;
  • 19.
    List::MoreUtils $has_quiche = any{ /bquicheb/ } @foods; # T/F $all_unicorns = all { $_ eq 'unicorn' } @animals; # T/F @joint_incomes = pairwise { $a + $b } @his, @hers; @evens_odds = part { $_ % 2 } 1 .. 9; # LOLs
  • 20.
    List::MoreUtils “natatime” my @alphabet= ( 'a' .. 'z' ); my $iterator = natatime 3, @alphabet; while( my @chars = $iterator->() ) { print “@charsn”; } __END__ a b c d e f … y z
  • 21.
    List::MoreUtils ● Too manyto mention them all. – See https://metacpan.org/module/List::MoreUtils
  • 22.
    Resources ● perldoc -fgrep ● perldoc -f map ● perldoc -f sort ● perldoc List::Util ● https://metacpan.org/module/List::MoreUtils
  • 23.
    Salt Lake PerlMongers http://saltlake.pm.org Slides on slideshare.net http://www.slideshare.net/daoswald/perls-functional-functions
  • 24.