How to create higher-order functions in Perl?
Question
How to create higher-order functions in Perl?
In Perl, higher-order functions are subroutines that can take other subroutines as arguments, return subroutines as results, or both. This capability enables a functional programming style where you build flexible and reusable abstractions by manipulating code references.
Since Perl treats subroutines as first-class values with the sub keyword and code references, creating higher-order functions (HOFs) is quite natural. Perl’s flexibility, often described by the acronym TMTOWTDI ("There’s More Than One Way To Do It"), means you have multiple ways to pass, store, and return code references.
Key Concepts
- Code references: Created with
sub { ... }or\\&subname, these are scalar references to anonymous or named subroutines. - Passing subs as arguments: You can pass code refs to other subs and invoke them with the
->()syntax. - Returning subs from subs: A subroutine can return a code reference, which can later be called, allowing creation of closures.
- Closures: Code references that capture variables from the enclosing scope, enabling stateful behavior.
Example: Creating a Higher-Order Function
Below is a simple example that demonstrates a higher-order function called make_multiplier. It takes a number and returns a subroutine reference that multiplies its argument by that number. This leverages Perl closures and code references:
#!/usr/bin/perl
use strict;
use warnings;
# Higher-order function: returns a sub ref that multiplies input by $factor
sub make_multiplier {
my ($factor) = @_;
return sub {
my ($input) = @_;
return $input * $factor;
};
}
# Create a doubler and a tripler
my $doubler = make_multiplier(2);
my $tripler = make_multiplier(3);
print "5 doubled is ", $doubler->(5), "\n"; # prints 10
print "7 tripled is ", $tripler->(7), "\n"; # prints 21
# Another example: applying a function passed as argument
sub apply_function {
my ($func, $value) = @_;
return $func->($value);
}
my $square = sub { my $x = shift; return $x * $x };
print "Square of 6 is ", apply_function($square, 6), "\n"; # prints 36
Explanation
make_multiplieraccepts a number,$factor, and returns an anonymous subroutine capturing this value via closure.- This returned subroutine can then be called on a value to multiply it by
$factor. - The example also shows
apply_function, a higher-order subroutine that takes a code reference and a value and calls the code reference on the value. - Use of
->()to invoke code references is required. - Strict and warnings pragmas are used to catch common mistakes.
Common Pitfalls
- Forgetting to use
->()to call a code reference; writing$func($arg)will call a subroutine named$func, not a code reference. - Not properly capturing lexical variables in closures, leading to unexpected behavior if the variables change later.
- Passing named subs by reference requires
\\&subnamesyntax to get a code reference. - Beware of contexts: scalar vs list context can affect results when subs return lists.
Version Notes
This style of higher-order programming works in Perl 5 and later. Since Perl 5.10+, features like state variables can further enhance closure usage. No external modules are required.
In summary, building higher-order functions in Perl primarily involves carefully handling code references and closures. This enables powerful and reusable abstractions common in functional programming paradigms.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 7ms
5 doubled is 10
7 tripled is 21
Square of 6 is 36
(empty)Was this helpful?
Related Questions
- How to use the return statement early in a Perl subroutine?
- How to use shift to get subroutine arguments in Perl?
- How to use caller() to get subroutine call information in Perl?
- How to call a subroutine as a method in Perl?
- How to use state variables in Perl subroutines?
- How to check the number of arguments passed to a subroutine in Perl?