tl;dr: A major version bump should be a semantic versioning change to the default feature bundle.
I’ve heard calls for a Perl 7 along the lines of 5.32 but with better defaults. This document describes how I imagine that might possibly work.
I have not paid any attention to actual discussions/flamewars going on about Perl 7. I have no idea about the technical feasibility of what I describe. And I no longer have time for, nor an economic stake in, contributing to make it happen.
I offer this in the spirit of a knowledgeable community member imagining the future I’d like to live in.
Perl 5 already has a mechanism for opting into different semantics via the
feature pragma. Features are
granular bits of syntax or semantics like
These are organized into ‘feature bundles’, like
:5.12, which are enabled
use feature ':5.12', or via a shortcut like
[For the moment, I’m going to ignore the peculiarity that
use feature ':5.12' doesn’t set
use v5.12 does.1]
This has the very nice property that any Perl code that declares a requirement on a version of Perl gets the semantics released with that version, even when run on a newer Perl.
Because the feature bundles effectively follow semantic versioning, each minor version might add features to the default bundle for that version. For example:
:5.14 say state switch unicode_strings :5.16 say state switch unicode_strings unicode_eval evalbytes current_sub fc
If our code was written with
use v5.14 – which works on any perl from
v5.14 or later – and we decided that we really needed to add
fc, we can
bump our declaration to
use v5.16. This is safe, because we know that
minor versions only add features and never remove them.
But let’s say that we decide that the
switch feature is a problem, and we
want to remove it from the default bundle in the next version of Perl,
whatever that might be. Following the rules of semantic versioning, we
never remove functionality in a minor version, so we need a major version
bump. In this case, 6 is out, so we need 7.
To illustrate this, let’s ignore all the versions of Perl after v5.16 and
their features, and imagine a counterfactual history where v7 followed
v5.16 with a feature bundle that removes
switch and also adds a new,
:7.0 say state unicode_strings unicode_eval evalbytes current_sub fc klingon
Seeing a new major version, we’d be careful bumping from
use v5.16 to
use v7.0 to get
klingon because we know there might be a breaking
change. If we want to get ‘switch’ back, we can add it back with the
pragma because it’s still there, just not part of the default bundle:
use v7.0; use feature 'switch';
This seems like a completely natural reason for major version bumps and a very familiar, explainable mechanism for it.
A major version bump is just a semantic
versioning change to the default feature bundle. Code with older
declarations gets the older semantics. Code that needs a mix of old and
new semantics can restore them with
But how do we remove things that aren’t features? The answer is
straightforward: retroactively declare them to be features. This has
already happened for
indirect. If you look at the
feature docs in
Perl 5.32, you’ll see that
indirect has been added to the
feature bundle and every bundle after it. This creates the opportunity to
indirect in a
This works in a wonderfully subtle way. Consider
indirect. On Perl
5.30, having no declaration or a
use v5.30 declaration gave you
indirect because it was implicit. On Perl 5.32, the same is true. If
you try to turn off
indirect with the
feature pragma you need perl 5.32
anyway, so the only sensible use of the feature is this:
use v5.32; no feature 'indirect';
I think retroactive feature definition is how all removals should work. And if for some technical reason, some piece of Perl’s syntax or semantics that people want to remove can’t be expressed as a feature, then it shouldn’t be removed.
The essential question that I think is at the crux of the controversy over
plans for Perl 7 is this: what features are enabled when no
use vX pragma
is in force? One view is that it should default to the feature bundle of the
current version of Perl – i.e. no minimum version declaration means “latest
features”, including default strictures.
I think this is misguided.
For one, this is the critical change that breaks legacy code. If no
version declaration is instead taken as equivalent to
use v5, then legacy
code continues to work.
Also, I believe code benefits from version declarations. Code with a version declaration is protected from being run on older perls. If code is assuming v7 semantics, shouldn’t it fail to run on v5.X? And the version declaration provides forward compatibility. It protects code from future versions of Perl that change semantics but provide backwards compatibility. If code is assuming v7 semantics, shouldn’t it continue to run on v8 without modification?
The ‘cost’ of requiring users to write
use v7; is small. It’s not hard
to teach or learn. It leads to better, safer code. And it is kinder to
The next conundrum I have is about
strict. Currently, we
have the somewhat weird situation where
use v5.12 or later enables
use feature ':5.12' does not.1
use feature ':7.0' enable
strict? It would be more consistent
with the rest of the feature system: adding a
would make the change visible to people comparing feature bundles across
versions. But it’s also a break with the past. On balance, I think it
would be a benefit. Default warnings could be handled the same way.
On the other hand, I’ve heard through the grapevine that strict by default
is complicated (though I’ve heard it in the context of default strict
without a version declaration). If leaving the current system alone is
less complex to implement, I think that’s fine, too. Most people will be
use v7, not
use feature ':7.0' and will get the benefit
This leads me to consider the one-liner flags
default_strict is not a Perl 7 feature and if no version declaration is
use v5, then it all works as you expect already in Perl 5.
-e flag is equivalent to code without a version declaration. The
flag is equivalent to
use feature ':<current>' (which doesn’t turn on
If default warnings work like default strict (on with
use v7 and not with
:7.0 feature bundle), then it still works consistently as one expects.
But even if
default_warnings are features enabled
:7.0 bundle, the definitions of
-E are still
-e use v5 -E use v7; no strict; no warnings;
Why continue to have
-E avoid strict and warnings? I think that’s how
most people use one-liners and so minimizes annoyance and breakage. And it
minimizes conflict with the
The last thing I want to consider is when old features should be removed.
If Perl 7 removes
indirect from the default bundle, but keeps it
available for backwards compatibility (presumably marked ‘deprecated’), how
long should it stay available? If Perl 8 removes it, then code that
use v5 should error because Perl 8 can’t satisfy the feature
There is cost to maintaining old code and there is cost to breaking user code. I suspect the right answer is that most features should stay around for backwards compatibility for a long time. But this is no different than the deprecation policy we have today and I see no reason for that to change with Perl 7 and beyond.
So what would I like in the Perl 7 feature bundle?
- Add default strict and warnings – either as part of the feature bundle
or enabled only with
signaturesas a non-experimental feature. I think this requires adding a retroactive
prototypesfeature to bundles before v7.
switch(because it requires an experimental feature to work).
I think that’s enough. It’s a step into a future where Perl major versions are defined by the breaking feature bundle changes they make.
In my proposed case, that’s removing three features (
and a newly-defined
prototypes), and adding two code-breaking features
default_warnings (either as literal features or via
Breaking changes should be rare. But they should be possible. The approach I’ve described makes it possible and minimizes the impact on legacy code.
I don’t know if what I’ve described is technically feasible, but as a user of Perl 5 and hopefully Perl 7, I hope it is.
use v5.12and later turn on only the parts of strict that haven’t been explicitly disabled previously. E.g.
no strict 'refs'; use v5.12;turns on strict except for strict refs. This complicates the design of Perl 7 default strict a bit, but I think that’s a small detail that can be worked out reasonably any number of ways without jeopardizing the vision I’ve described. ↩︎