This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)
Task #2 this week is no doubt about first class functions, but gets more specific, asking us to have a go at function composition:
Create
Task #2sub compose($f, $g)
which takes in two parameters$f
and$g
as subroutine refs and returns subroutine ref i.e.compose($f, $g)->($x) = $f->($g->($x))
Before we get too far ahead of ourselves, let’s briefly review what these terms mean.
First Class Functions
A language that supports first class functions simply allows you to pass functions around like any other variable. Passing anonymous functions (also known as lambda functions) around is usually included in this definition as well. Perl makes this easy:
my $add2 = sub { $_[0] + 2 }; # Returns a sub that adds 2 to its argument
$sub->(5); # Returns 7
That example may not be the most compelling, but for some motivation, look no farther than Perl’s map
or grep
builtins. When you call something like map { $_ * $_ } 1..10
to get the first ten square numbers, that block { $_ * $_ }
is an anonymous subroutine.
First class functions are incredibly useful, and deserve more discussion than I can cram into this blog post, so perhaps I’ll do them justice with a longer dedicated post in the future.
Function Composition
Function composition is a distinct concept in mathematics. In computer science, it depends on first class functions, but is otherwise not related. Function composition, often denoted with the ∘ operator, takes two functions f and g and produces a new function:
\(h = g \circ f \text{ such that } h(x) = g(f(x)) \)
The reason it’s usually written as g ∘ f is that in plain English, g follows f, because we are feeding the output of f into g. Of course, f and g are just symbols, so they can be swapped to match the task description with no issues:
\(h = f \circ g \text{ such that } h(x) = f(g(x)) \)
Perl
Now that we’ve gotten all of the pesky definitions out of the way, the code is … well, there’s hardly any code at all, really. Here’s a function that generates the composition h = f ∘ g:
sub comp {
my ($f, $g) = @_;
sub { $f->($g->(@_)) }
}
Here’s an example usage that calculates the sum of squares of a list of numbers:
use List::Util qw< sum0 >;
my $squares = sub { map { $_ * $_ } @_ };
my $h = comp( \&sum0, $squares );
say "The sum of squares for 1..10 = " . $h->(1..10); # 385
I chose to use List::Util
‘s sum0
function so I could demonstrate how to pass in a reference to a named function. The $squares
function shows how to use a variable. I could have also done this as an anonymous function:
my $h = comp( \&sum0, sub { $_ * $_ } @_ } );
Raku
Raku’s first class function support is very good. In fact, the language was designed around higher order features like this, so there are some built-in helpers we can use, such as the composition operator. That’s right, we can use ∘
or o
right in our code to do the function composition. I could stick this into a comp
function like I did with the Perl example, but that seems less expressive to me.
my &sum = sub { [+] @_ };
my &square = sub { @_ »*« @_ };
my &h = &sum ∘ □
say &h(1..10); # 385
First class functions open up endless possibilities in your code.