Try Perl 5.36's New Syntax and Safer Defaults
Perl 5.36 quietly tightened a few defaults and added syntax worth trying before you rely on it in production code. In about 15 minutes you will test the 5.36 feature bundle, write a subroutine with a real signature, try the new -g whole-input flag, and see which of the newer features are still experimental. Every example here is read-only and leaves nothing behind.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide follows perl5360delta(1), the release note for Perl 5.36.0. The manpage installed on this machine comes from perl-doc version 5.38.2-3.2ubuntu0.6 and is rendered for Perl 5.38.2, so the examples check out locally, but the document itself only describes what 5.36.0 added, not everything the later interpreter picked up since.
1. Check the interpreter before changing code
Start by recording which Perl your shell will actually run:
$ command -v perl
/usr/bin/perl
$ perl -e 'printf "%vd\n", $^V'
v5.38.2
The release note compares 5.36.0 with 5.34.0. A later Perl normally keeps these features, but it can also change experimental behaviour underneath you. If a deployment must stay on 5.36 semantics, check the interpreter in that actual deployment rather than trusting whatever your workstation happens to have installed.
Checkpoint
The version command should print the interpreter that will run your script. Wrong path or wrong version means stop and fix the environment first, not install another Perl into a shared system just to follow along.
2. Turn on the 5.36 feature bundle
Put use v5.36; near the top of any script that needs the release's language defaults:
use v5.36;
sub add ($x, $y) {
return $x + $y;
}
print add(2, 3), "\n";
Or skip the source file and pass the same code straight to -e:
$ perl -e 'use v5.36; sub add ($x, $y) { $x + $y }; print add(2, 3), "\n"'
5
- Signatures are stable in this bundle, and so is the
isaoperator. - Warnings turn on automatically.
indirectandmultidimensionalfeatures turn off. Think of it as stricter language defaults, not a substitute for actually reviewing the code you are upgrading.
A signature is not a type declaration: $x and $y still hold ordinary Perl values, the example only adds positional argument binding. Do not mix a signature with @_ or $_[0] while you are upgrading. The 5.36 release note flags access to that legacy argument array inside a signatured subroutine as experimental, with its own warning category.
3. Use -g when a filter needs the whole input
Perl 5.36 adds -g as a shorter alias for -0777. It undefines the input record separator, so a filter reads the entire input as one string instead of chewing through it line by line.
$ printf 'alpha\nbeta\n' | perl -g -pe 's/\n/|/g'
alpha|beta|
The older spelling gives you the identical result:
$ printf 'alpha\nbeta\n' | perl -0777 -pe 's/\n/|/g'
alpha|beta|
Warning
This is handy for a deliberately small whole-document transform, but it is not a free performance win. The input has to fit in memory as one record. Never point a -g one-liner at an unbounded log, a device stream or a user-uploaded file without an explicit size limit. For large input, use a streaming design instead.
Checkpoint
Both commands above should produce one transformed string. If your filter relies on per-line state, do not swap its normal record handling for -g.
4. Try the new builtin functions carefully
Perl 5.36 adds the core builtin module with functions like reftype, trim, indexed, true, false, is_bool, weaken, blessed, ceil and floor. The whole module is experimental in this release, so you opt in knowingly and expect warnings by default.
$ perl -we 'use v5.36; use builtin "reftype"; print builtin::reftype([]), "\n"'
Built-in function 'builtin::reftype' is experimental at -e line 1.
ARRAY
That warning is doing its job during evaluation. Suppressing it is a local decision, not proof the interface is stable:
use v5.36;
use builtin 'reftype';
no warnings 'experimental::builtin';
print reftype([]), "\n";
Use the documented lexical import form when you want a short name, and keep experimental calls behind a small interface in application code so a future Perl upgrade only needs one place to check. Do not treat builtin::true and builtin::false as a strict Boolean type system: Perl values stay flexible even though the new Boolean tracking preserves their Boolean nature.
5. Treat defer, try and multi-value loops as experiments
The release also adds several experimental syntax features:
deferblocks run when their enclosing scope exits, after execution reaches the block. They will not run if control leaves the scope before the declaration is reached, and they cannot be escaped withreturn,gotoor loop control.try/catchcan now have afinallyblock.- Multi-value iteration such as
for my ($key, $value) (%hash)is marked experimental too, under theexperimental::for_listwarning.
$ perl -we 'use v5.36; use feature "defer"; no warnings "experimental::defer"; { defer { print "cleanup\n" }; print "body\n" }'
body
cleanup
That restriction on escaping a defer block matters when you adapt cleanup code: test the control-flow paths rather than assuming it behaves like a destructor.
$ perl -we 'use v5.36; use feature "try"; no warnings "experimental::try"; try { die "bad\n" } catch ($e) { print "caught:$e" } finally { print "finally\n" }'
caught:bad
finally
Do not ship any of these constructs into a compatibility-sensitive module without testing the oldest Perl you claim to support.
6. Check upgrade traps before committing
A physically empty sort is now a compile-time error. Both of these forms stop being a harmless empty list in 5.36:
@items = sort; # compile-time error in 5.36
@items = sort (); # compile-time error in 5.36
Use an explicit empty list if that is what the code actually means, or give sort the real list. Compile the whole program in CI: a runtime test that never touches the affected branch will not catch a compile-time error.
Also review nested version declarations. After use v5.11 or later, a later use v5.8 emits a deprecation warning. If genuinely different language versions must coexist, isolate them in separate lexical blocks; that is usually a sign the upgrade needs a clearer module boundary anyway.
Done means
- Verified the Perl executable and version used by the test.
- Compiled a signatured subroutine under
use v5.36and got the expected result. - Understood
-gas an all-in-one-record read, used only on bounded data. - Kept experimental features visible:
builtin,defer,tryand multi-value loops all still flagged and tested. - Checked for empty
sortcalls and problematic nesteduse VERSIONdeclarations.