34 at 34 for v5.34: Modern Perl features for Perl’s birthday
Tags: perl, programming, opensource, news
Published: 2021-12-21 16:52:30

---
title: 34 at 34 for v5.34: Modern Perl features for Perl’s birthday
published: true
date: 2021-12-21 15:00:00 UTC
tags: Perl,programming,opensource,news
canonical_url: https://phoenixtrap.com/2021/12/21/34-at-34-for-v5-34-modern-perl-features-for-perls-birthday/
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xkw7qjr2mga8ik5tszyz.jpg
---

Friday, December 17, 2021, marked the [thirty-fourth birthday](https://github.com/Perl/perl5/commit/8d063cd8450e59ea1c611a2f4f5a21059a2804f1) of the Perl programming language, and coincidentally this year saw the [release of version 5.34](https://www.nntp.perl.org/group/perl.perl5.porters/2021/05/msg260110.html). There are plenty of Perl developers out there who haven’t kept up with recent (and not-so-recent) improvements to the language and its ecosystem, so I thought I might list a batch. (You may have seen some of these before in May’s post [“Perl can do that now!”](https://phoenixtrap.com/2021/05/25/perl-can-do-that-now/))

## [The `feature` pragma](https://perldoc.perl.org/feature)

[Perl v5.10 was released in December 2007](https://www.nntp.perl.org/group/perl.perl5.porters/2007/12/msg131636.html), and with it came `feature`, a way of enabling new syntax without breaking backward compatibility. You can enable individual features by name (e.g., `use feature qw(say fc);` for the `say` and `fc` keywords), or by using a [feature bundle](https://perldoc.perl.org/feature#FEATURE-BUNDLES) based on the Perl version that introduced them. For example, the following:

```perl
use feature ':5.34';
```

…gives you the equivalent of:

```perl
use feature qw(bareword_filehandles bitwise current_sub evalbytes fc indirect multidimensional postderef_qq say state switch unicode_eval unicode_strings);
```

Boy, that’s a mouthful. _Feature bundles are good._ The corresponding bundle also gets [implicitly loaded](https://perldoc.perl.org/feature#IMPLICIT-LOADING) if you specify a minimum required Perl version, e.g., with `use v5.32;`. If you `use v5.12;` or higher, [`strict` mode](https://perldoc.perl.org/strict) is enabled for free. So just say:

```perl
use v5.34;
```

And lastly, one-liners can use the [`-E` switch](https://perldoc.perl.org/perlrun#-E-commandline) instead of `-e` to enable all features for that version of Perl, so you can say the following on the command line:

```shell
perl -E 'say "Hello world!"'
```

Instead of:

```shell
perl -e 'print "Hello world!\n"'
```

Which is great when you’re trying to save some typing.

## [The `experimental` pragma](https://perldoc.perl.org/experimental)

Sometimes new Perl features need to be [driven a couple of releases around the block](https://perldoc.perl.org/perlpolicy#experimental) before their behavior settles. Those experiments are documented in [the perlexperiment page](https://perldoc.perl.org/perlexperiment), and usually, you need both a `use feature` (see above) and `no warnings` statement to safely enable them. Or you can simply pass a list to `use experimental` of the features you want, e.g.:

```perl
use experimental qw(isa postderef signatures);
```

## Ever-expanding [`warnings` categories](https://perldoc.perl.org/warnings#Category-Hierarchy)

[March 2000 saw the release of Perl 5.6](https://www.nntp.perl.org/group/perl.perl5.porters/2000/03/msg10668.html), and with it, the expansion of the [`-w` command-line switch](https://perldoc.perl.org/perlrun#-w) to a system of fine-grained controls for warning against “dubious constructs” that can be turned on and off depending on the lexical [scope](https://perldoc.perl.org/perlintro#Variable-scoping). What started as [26 main and 20 subcategories](https://perldoc.perl.org/5.6.0/perllexwarn#Category-Hierarchy) has [expanded into 31 main and 43 subcategories](https://perldoc.perl.org/warnings#Category-Hierarchy), including warnings for the aforementioned experimental features.

As the [relevant Perl::Critic policy says](https://metacpan.org/pod/Perl::Critic::Policy::TestingAndDebugging::RequireUseWarnings#DESCRIPTION), “Using warnings, and paying attention to what they say, is probably the single most effective way to improve the quality of your code.” If you must violate warnings (perhaps because you’re rehabilitating some legacy code), you can isolate such violations to a small scope and individual categories. Check out the [strictures module on CPAN](https://metacpan.org/pod/strictures) if you’d like to go further and make a safe subset of these categories fatal during development.

## Document other recently-introduced syntax with [Syntax::Construct](https://metacpan.org/pod/Syntax::Construct)

Not every new bit of Perl syntax is enabled with a `feature` guard. For the rest, there’s E. Choroba’s [Syntax::Construct module on CPAN](https://metacpan.org/pod/Syntax::Construct). Rather than having to remember which version of Perl introduced what, Syntax::Construct lets you declare only what you use and provides a helpful error message if someone tries to run your code on an older unsupported version. Between it and the `feature` pragma, you can prevent many head-scratching moments and give your users a chance to either upgrade or workaround.

## Make built-in functions throw exceptions with `autodie`

Many of Perl’s built-in functions only return false on failure, requiring the developer to check every time whether a file can be `open`ed or a `system` command executed. The lexical [`autodie` pragma](https://perldoc.perl.org/autodie) replaces them with versions that [raise an exception](https://perldoc.perl.org/functions/die) with an [object](https://perldoc.perl.org/autodie::exception) that can be interrogated for further details. No matter how many functions or methods deep a problem occurs, you can choose to catch it and respond appropriately. This leads us to…

## [`try`/`catch` exception handling](https://perldoc.perl.org/perlsyn#Try-Catch-Exception-Handling) and [Feature::Compat::Try](https://metacpan.org/pod/Feature::Compat::Try)

[This year’s Perl v5.34 release](https://www.nntp.perl.org/group/perl.perl5.porters/2021/05/msg260110.html) introduced [experimental `try`/`catch` syntax](https://perldoc.perl.org/perlsyn#Try-Catch-Exception-Handling) for exception handling that should look more familiar to users of other languages while handling the [issues](https://metacpan.org/pod/Try::Tiny#BACKGROUND) surrounding using [block `eval`](https://perldoc.perl.org/functions/eval#Block-eval) and testing of the [special `$@` variable](https://perldoc.perl.org/variables/%24@). If you need to remain compatible with older versions of Perl (back to v5.14), just use the [Feature::Compat::Try module from CPAN](https://metacpan.org/pod/Feature::Compat::Try) to automatically select either v5.34’s native `try`/`catch` or a subset of the functionality provided by [Syntax::Keyword::Try](https://metacpan.org/pod/Syntax::Keyword::Try).

## Pluggable keywords

The abovementioned Syntax::Keyword::Try was made possible by the [introduction of a pluggable keyword mechanism in 2010’s Perl v5.12](https://perldoc.perl.org/perl5120delta#Pluggable-keywords). So was the [Future::AsyncAwait](https://metacpan.org/pod/Future::AsyncAwait) asynchronous programming library and the [Object::Pad](https://metacpan.org/pod/Object::Pad) testbed for new object-oriented Perl syntax. If you’re handy with C and [Perl’s XS glue language](https://perldoc.perl.org/perlxs), check out Paul “LeoNerd” Evans’ [XS::Parse::Keyword](https://metacpan.org/pod/XS::Parse::Keyword) module to get a leg up on developing your own syntax module.

## Define `package`s with versions and blocks

Perl v5.12 also helped reduce clutter by enabling a [`package` namespace declaration](https://perldoc.perl.org/functions/package) to [also include a version number](https://perldoc.perl.org/perl5120delta#New-package-NAME-VERSION-syntax), instead of requiring a separate `our $VERSION = ...;` v5.14 further refined `package`s to be [specified in code blocks](https://perldoc.perl.org/perl5140delta#package-block-syntax), so a namespace declaration can be the same as a lexical scope. Putting the two together gives you:

```perl
package Local::NewHotness v1.2.3 {
    ...
}
```

Instead of:

```perl
{
    package Local::OldAndBusted;
    use version 0.77; our $VERSION = version->declare("v1.2.3");
    ...
}
```

I know which I’d rather do. (Though you may want to also `use Syntax::Construct qw(package-version package-block);` to help along with older installations as [described above](#syntax-construct).)

## [The `//` defined-or operator](https://perldoc.perl.org/perlop#Logical-Defined-Or)

This is an easy win [from Perl v5.10](https://perldoc.perl.org/perl5100delta#Defined-or-operator):

```perl
defined $foo ? $foo : $bar # replace this
$foo // $bar               # with this
```

And:

```perl
$foo = $bar unless defined $foo # replace this
$foo //= $bar                   # with this
```

Perfect for assigning defaults to variables.

## [`state` variables](https://perldoc.perl.org/functions/state) only initialize once

Speaking of variables, ever want one to keep its old value the next time a scope is entered, like [in a `sub`](https://perldoc.perl.org/perlsub#Persistent-Private-Variables)? Declare it with `state` instead of `my`. Before [Perl v5.10](https://perldoc.perl.org/perl5100delta#state()-variables), you needed to [use a closure instead](https://perldoc.perl.org/perlsub#Persistent-variables-with-closures).

## Save some typing with `say`

[Perl v5.10’s bumper crop of enhancements](https://perldoc.perl.org/perl5100delta#Core-Enhancements) also included the [`say` function](https://perldoc.perl.org/functions/say), which handles the common use case of `print`ing a string or list of strings with a newline. It’s less noise in your code and saves you four characters. What’s not to love?

## Note unimplemented code with `...`

The [`...` ellipsis statement](https://perldoc.perl.org/perlsyn#The-Ellipsis-Statement) (colloquially “yada-yada”) gives you an easy placeholder for yet-to-be-implemented code. It parses OK but will throw an exception if executed. Hopefully, your [test coverage](https://metacpan.org/pod/Devel::Cover) (or at least [static analysis](https://metacpan.org/pod/Perl::Critic::Policy::ControlStructures::ProhibitYadaOperator)) will catch it before your users do.

## Loop and enumerate arrays with `each`, `keys`, and `values`

The `each`, `keys`, and `values` functions have always been able to operate on hashes. [Perl v5.12 and above make them work on arrays, too.](https://perldoc.perl.org/perl5120delta#each,-keys,-values-are-now-more-flexible) The latter two are mainly for consistency, but you can use `each` to iterate over an array’s indices and values at the same time:

```perl
while (my ($index, $value) = each @array) {
    ...
}
```

This can be [problematic in non-trivial loops](https://metacpan.org/pod/Perl::Critic::Policy::Community::Each), but I’ve found it helpful in quick scripts and one-liners.

## [`delete local` hash (and array) entries](https://perldoc.perl.org/perlsub#Localized-deletion-of-elements-of-composite-types)

Ever needed to `delete` an entry from a hash (e.g, an environment variable from `%ENV` or a signal handler from `%SIG`) just inside a block? [Perl v5.12 lets you do that](https://perldoc.perl.org/perl5120delta#delete-local) with `delete local`.

## Paired hash slices

Jumping forward to [2014’s Perl v5.20](https://www.nntp.perl.org/group/perl.perl5.porters/2014/05/msg215815.html), the [new `%foo{'bar', 'baz'}` syntax](https://perldoc.perl.org/perl5200delta#New-slice-syntax) enables you to [slice a subset of a hash](https://perldoc.perl.org/perldata#Key%2FValue-Hash-Slices) with its keys and values intact. Very helpful for cherry-picking or aggregating many hashes into one. For example:

```perl
my %args = (
    verbose => 1,
    name    => 'Mark',
    extra   => 'pizza',
);
# don't frob the pizza
$my_object->frob( %args{ qw(verbose name) };
```

## Paired array slices

Not to be left out, you can also [slice arrays](https://perldoc.perl.org/perldata#Index/Value-Array-Slices) in the same way, in this case returning indices and values:

```perl
my @letters   = 'a' .. 'z';
my @subset_kv = %letters[16, 5, 18, 12];
# @subset_kv is now (16, 'p', 5, 'e', 18, 'r', 12, 'l')
```

## More readable dereferencing

[Perl v5.20 introduced](https://perldoc.perl.org/perl5200delta#Experimental-Postfix-Dereferencing) and [v5.24 de-experimentalized](https://perldoc.perl.org/perl5240delta#Postfix-dereferencing-is-no-longer-experimental) a more readable [postfix dereferencing syntax](https://perldoc.perl.org/perlref#Postfix-Dereference-Syntax) for navigating nested data structures. Instead of using `{`braces`}` or smooshing sigils to the left of identifiers, you can use a postfixed sigil-and-star:

```perl
push @$array_ref,    1, 2, 3; # noisy
push @{$array_ref},  1, 2, 3; # a little easier
push $array_ref->@*, 1, 2, 3; # read from left to right
```

So much of web development is slinging around and picking apart complicated [data structures](https://perldoc.perl.org/perldsc) via [JSON](https://www.json.org/), so I welcome anything like this to reduce the cognitive load.

## `when` as a statement modifier

[Starting in Perl v5.12](https://perldoc.perl.org/perl5120delta#when-as-a-statement-modifier), you can use the [experimental switch feature](https://perldoc.perl.org/perlsyn#Switch-Statements)’s `when` keyword as a postfix modifier. For example:

```perl
for ($foo) {
    $a =  1 when /^abc/;
    $a = 42 when /^dna/;
    ...
}
```

But I don’t recommend `when`, `given`, or `given`’s [smartmatch](https://perldoc.perl.org/perlop#Smartmatch-Operator) operations as they were [retconned as experiments in 2013’s Perl v5.18](https://perldoc.perl.org/perl5180delta#New-mechanism-for-experimental-features) and have remained so due to their [tricky behavior](https://perldoc.perl.org/perlsyn#Experimental-Details-on-given-and-when). I wrote about [some alternatives using stable syntax](https://phoenixtrap.com/2021/02/14/switching-up-my-switches/) back in February.

## Simple class inheritance with `use parent`

Sometimes in older object-oriented Perl code, you’ll see `use base` as a pragma to establish inheritance from another class. Older still is the direct manipulation of the [package’s special `@ISA` array](https://perldoc.perl.org/variables/@ISA). In most cases, both should be avoided in favor of `use parent`, which was [added to core in Perl v5.10.1](https://perldoc.perl.org/perl5101delta#parent).

Mind you, if you’re following the [Perl object-oriented tutorial’s advice and have selected an OO system](https://perldoc.perl.org/perlootut#PERL-OO-SYSTEMS) from CPAN, use its subclassing mechanism if it has one. [Moose](https://metacpan.org/pod/Moose#extends-(@superclasses)), [Moo](https://metacpan.org/pod/Moo#extends), and [Class::Accessor’s “antlers” mode](https://metacpan.org/pod/Class::Accessor#Moose!) all provide an `extends` function; [Object::Pad provides an `:isa` attribute](https://metacpan.org/pod/Object::Pad#:isa) on its [`class` keyword](https://metacpan.org/pod/Object::Pad#class).

## Test for class membership with the [`isa` operator](https://perldoc.perl.org/perlop#Class-Instance-Operator)

As an alternative to the [`isa()` method](https://perldoc.perl.org/UNIVERSAL#%24obj-%3Eisa(-TYPE-)) provided to all Perl objects, [Perl v5.32 introduced](https://perldoc.perl.org/perl5320delta#The-isa-Operator) the experimental [`isa` infix operator](https://perldoc.perl.org/perlop#Class-Instance-Operator):

```perl
$my_object->isa('Local::MyClass')
# or
$my_object isa Local::MyClass
```

The latter can take either a bareword class name or string expression, but more importantly, it’s safer as it also returns false if the left argument is undefined or isn’t a `bless`ed object reference. The older `isa()` method will throw an exception in the former case and might return true if called as a class method when `$my_object` is actually a string of a class name that’s the same as or inherits from `isa()`’s argument.

## [Lexical subroutines](https://perldoc.perl.org/perlsub#Lexical-Subroutines)

[Introduced in Perl v5.18](https://perldoc.perl.org/perl5180delta#Lexical-subroutines) and [de-experimentalized in 2017’s Perl v5.26](https://perldoc.perl.org/perl5260delta#Lexical-subroutines-are-no-longer-experimental), you can now precede sub declarations with [`my`, `state`](https://perldoc.perl.org/perlsub#Lexical-Subroutines), or `our`. One use of the first two is truly private functions and methods, as described in [this 2018 Dave Jacoby blog](https://jacoby.github.io/perl/2018/08/29/use-perl-features-lexical_subs.html) and as part of [Neil Bowers’ 2014 survey](http://neilb.org/2014/07/24/private-functions.html) of private function techniques.

## [Subroutine signatures](https://perldoc.perl.org/perlsub#Signatures)

I’ve [written](https://phoenixtrap.com/2021/01/27/better-perl-with-subroutine-signatures-and-type-validation/) and [presented](https://phoenixtrap.com/2021/03/17/video-for-better-perl-subroutine-signatures-and-type-validation/) [extensively](https://phoenixtrap.com/2021/02/16/better-perl-more-on-signatures-and-types/) about signatures and alternatives over the past year, so I won’t repeat that here. I’ll just add that the [Perl 5 Porters](https://lists.perl.org/list/perl5-porters.html) development mailing list has been [making a concerted effort](https://www.nntp.perl.org/group/perl.perl5.porters/2021/11/msg261939.html) over the past month to hash out the remaining issues towards rendering this feature non-experimental. The popular Mojolicious real-time web framework also [provides a shortcut for enabling signatures](https://metacpan.org/dist/Mojolicious/view/lib/Mojolicious/Guides.pod#Signatures) and uses them extensively in examples.

## Indented here-documents with `<<~`

Perl has had shell-style [“here-document” syntax](https://perldoc.perl.org/perlop#%3C%3CEOF) for embedding multi-line strings of quoted text for a long time. [Starting with Perl v5.26](https://perldoc.perl.org/perlop#%3C%3CEOF), you can precede the delimiting string with a `~` character and Perl will both allow the ending delimiter to be indented as well as strip indentation from the embedded text. This allows for much more readable embedded code such as runs of HTML and SQL. For example:

```perl
if ($do_query) {
    my $rows_deleted = $dbh->do(<<~'END_SQL', undef, 42);
      DELETE FROM table
      WHERE status = ?
      END_SQL
    say "$rows_deleted rows were deleted."; 
}
```

## More readable chained comparisons

When I learned math in school, my teachers and textbooks would often describe multiple comparisons and inequalities as a single expression. Unfortunately, when it came time to learn programming every computer language I saw required them to be broken up with a series of `and` (or `&&`) operators. [With Perl v5.32, this is no more](https://perldoc.perl.org/perl5320delta#Chained-comparisons-capability):

```perl
if ( $x < $y && $y <= $z ) { ... } # old way
if ( $x < $y <= $z )       { ... } # new way
```

It’s more concise, less noisy, and more like what regular math looks like.

## Self-documenting named regular expression captures

Perl’s expressive [regular expression](https://perldoc.perl.org/perlre) matching and text-processing prowess are legendary, although overuse and poor use of readability enhancements often turn people away from them (and Perl in general). We often use regexps for extracting data from a matched pattern. For example:

```perl
if ( /Time: (..):(..):(..)/ ) { # parse out values
    say "$1 hours, $2 minutes, $3 seconds";
}
```

Named [capture groups](https://perldoc.perl.org/perlre#Capture-groups), [introduced in Perl v5.10](https://perldoc.perl.org/perl5100delta#Named-Capture-Buffers), make both the pattern more obvious and retrieval of its data less cryptic:

```perl
if ( /Time: (?<hours>..):(?<minutes>..):(?<seconds>..)/ ) {
    say "$+{hours} hours, $+{minutes} minutes, $+{seconds} seconds";
}
```

## More readable regexp character classes

The `/x` regular expression modifier already enables better readability by telling the parser to ignore most whitespace, allowing you to break up complicated patterns into spaced-out groups and multiple lines with code comments. [With Perl v5.26 you can specify `/xx`](https://perldoc.perl.org/perl5260delta#New-regular-expression-modifier-/xx) to also ignore spaces and tabs inside `[`bracketed`]` character classes, turning this:

```perl
/[d-eg-i3-7]/
/[!@"#$%^&*()=?<>']/
```

…into this:

```perl
/ [d-e g-i 3-7]/xx
/[! @ " # $ % ^ & * () = ? <> ']/xx
```

## [Set default regexp flags with the `re` pragma](https://perldoc.perl.org/re#'/flags'-mode)

[Beginning with Perl v5.14](https://perldoc.perl.org/re#'/flags'-mode), writing `use re '/xms';` (or any combination of [regular expression modifier flags](https://perldoc.perl.org/perlre#Modifiers)) will turn on those flags until the end of that lexical scope, saving you the trouble of remembering them every time.

## Non-destructive substitution with `s///r` and `tr///r`

The [`s///` substitution](https://perldoc.perl.org/perlop#s/PATTERN/REPLACEMENT/msixpodualngcer) and [`tr///` transliteration](https://perldoc.perl.org/perlop#tr/SEARCHLIST/REPLACEMENTLIST/cdsr) operators typically change their input directly, often in conjunction with the [`=~` binding operator](https://perldoc.perl.org/perlop#Binding-Operators):

```perl
s/foo/bar/; # changes the first foo to bar in $_
$baz =~ s/foo/bar/; # the same but in $baz
```

But what if you want to leave the original untouched, such as when processing an array of strings with a `map`? [With Perl v5.14 and above, add the `/r` flag](https://perldoc.perl.org/perl5140delta#Non-destructive-substitution), which makes the substitution on a copy and returns the result:

```perl
my @changed = map { s/foo/bar/r } @original;
```

## [Unicode case-folding with `fc`](https://perldoc.perl.org/functions/fc) for better string comparisons

Unicode and character encoding in general are complicated beasts. Perl has [handled Unicode since v5.6](https://perldoc.perl.org/perl56delta#Unicode-and-UTF-8-support) and has kept pace with fixes and support for updated standards in the intervening decades. If you need to test if two strings are equal regardless of case, use the [`fc` function](https://perldoc.perl.org/functions/fc) introduced [in Perl v5.16](https://perldoc.perl.org/perl5160delta#New-function-fc-and-corresponding-escape-sequence-%5CF-for-Unicode-foldcase).

## Safer processing of file arguments with `<<>>`

The `<>` null filehandle or “diamond operator” is often used in [`while` loops](https://perldoc.perl.org/perlsyn#Compound-Statements) to process input per line coming either from standard input (e.g., piped from another program) or from a list of files on the command line. Unfortunately, it uses a [form of Perl’s `open` function](https://perldoc.perl.org/functions/open#open-FILEHANDLE,EXPR) that interprets special characters such as pipes (`|`) that would allow it to insecurely [run external commands](https://perldoc.perl.org/perlopentut#Opening-Pipes). Using the `<<>>` “double diamond” operator [introduced in Perl v5.22](https://perldoc.perl.org/perl5220delta#New-double-diamond-operator) forces `open` to treat all command-line arguments as file names only. For older Perls, the [perlop documentation](https://perldoc.perl.org/perlop#I/O-Operators) recommends the [ARGV::readonly CPAN module](https://metacpan.org/pod/ARGV::readonly).

## Safer loading of Perl libraries and modules from `@INC`

[Perl v5.26 removed the ability for all programs to load modules by default from the current directory](https://perldoc.perl.org/perl5260delta#Removal-of-the-current-directory-(%22.%22)-from-@INC), closing a security vulnerability originally identified and fixed as [CVE-2016–1238](https://nvd.nist.gov/vuln/detail/CVE-2016-1238) in previous versions’ included scripts. If your code relied on this unsafe behavior, the [v5.26 release notes include steps](https://perldoc.perl.org/perl5260delta#Removal-of-the-current-directory-(%22.%22)-from-@INC) on how to adapt.

## [HTTP::Tiny](https://perldoc.perl.org/HTTP::Tiny) simple HTTP/1.1 client included

To bootstrap access to [CPAN](https://cpan.org/) on the web in the possible absence of external tools like `curl` or `wget`, [Perl v5.14 began including the HTTP::Tiny module](https://perldoc.perl.org/HTTP::Tiny). You can also use it in your programs if you need a simple web client with no dependencies.

## [Test2](https://perldoc.perl.org/Test2): The next generation of Perl testing frameworks

Forked and refactored from the venerable [Test::Builder](https://perldoc.perl.org/Test::Builder) (the basis for the [Test::More](https://perldoc.perl.org/Test::More) library that many are familiar with), [Test2](https://perldoc.perl.org/Test2) was included in the core module library [beginning with Perl v5.26](https://perldoc.perl.org/5.26.0/perlmodlib#Test2). I’ve [experimented recently](https://phoenixtrap.com/tag/test2/) with using the [Test2::Suite](https://metacpan.org/pod/Test2::Suite) CPAN library instead of Test::More and it looks pretty good. I’m also intrigued by [Test2::Harness](https://metacpan.org/pod/Test2::Harness)’ support for threading, forking, and preloading modules to reduce test run times.

## [Task::Kensho](https://metacpan.org/pod/Task::Kensho): Where to start for recommended Perl modules

This last item may not be included when you install Perl, but it’s where I turn for a collection of well-regarded CPAN modules for accomplishing a wide variety of common tasks spanning from [asynchronous programming](https://metacpan.org/pod/Task::Kensho::Async) to [XML](https://metacpan.org/pod/Task::Kensho::XML). Use it as a starting point or [interactively](https://metacpan.org/dist/App-cpanminus/view/lib/App/cpanminus/fatscript.pm#-interactive) select the mix of libraries appropriate to your project.

* * *

And there you have it: a selection of 34 features, enhancements, and improvements for the first 34 years of Perl. What’s your favorite? Did I miss anything? Let me know in the comments.

* * *

_Cover image: ["My birthday cake"](https://www.flickr.com/photos/93472573@N00/5372262156) by [Wesley Bowler](https://www.flickr.com/photos/frosted_peppercorn/) is licensed under [CC BY-NC-SA 2.0](https://creativecommons.org/licenses/by-nc-sa/2.0/?ref=openverse&atype=html)_