1 of 49

Perl in 2025

Paul “LeoNerd” Evans (PEVANS)

2 of 49

Perl in 2025 2030

Paul “LeoNerd” Evans (PEVANS)

3 of 49

Perl in 2025

2020 Perl Advent Calendar

Turned into a presentation "Perl in 2025"

4 of 49

Completed

try/catch copied from Syntax::Keyword::Try

Subroutine signatures are now stable

use v5.40;��try {� some_func();�}�catch ( $e ) {� warn "It failed - $e\n";�}

use v5.36;��sub add ( $x, $y ) {� return $x + $y;�}

5 of 49

In Progress

class/field/method copied from Object::Pad

use v5.40;�use feature 'class';

class Point {

field $x :param :reader = 0;

field $y :param :reader = 0;

method describe () {

say "A point at ($x, $y)";

}

}

6 of 49

Perl in 2025

On CPAN right now

7 of 49

CPAN Experiments

Many modules in the Syntax::Keyword::* space

Provides new syntax in the form of leading keywords with custom parsing

  • Syntax::Keyword::Try
  • Object::Pad
    • could have been called Syntax::Keyword::Class

8 of 49

CPAN Experiments�Syntax::Keyword::Match

Dispatch similar to given/when but with explicit comparison operator

use v5.18;

use Syntax::Keyword::Match;

match($var : eq) {

case("abc") { ... }

case("def") { ... }

case("1.0") { ... }

otherwise { ... }

}

if ($var eq "abc") { ... }

elsif($var eq "def") { ... }

elsif($var eq "1.0") { ... }

else { ... }

9 of 49

CPAN Experiments�Syntax::Keyword::Match

Dispatch similar to given/when but with explicit comparison operator

use v5.18;

use Syntax::Keyword::Match;

match(some_func() : eq) {

case("abc") { ... }

case("def") { ... }

case("1.0") { ... }

otherwise { ... }

}

if (some_func() eq "abc") { ... }

elsif(some_func() eq "def") { ... }

elsif(some_func() eq "1.0") { ... }

else { ... }

10 of 49

CPAN Experiments�List::Keywords

Same syntax as List::Util functionals, just more efficient

use v5.14;

use List::Keywords 'any';

my @boxes = ...;

if( any { $_->size > 100 } @boxes ) {

say "There are some large boxes here";

}

Syntax::Keyword::Any ?

11 of 49

CPAN Experiments�Future::AsyncAwait

Convenient syntax for asynchronous code/data flow using futures

use v5.22;

use Future::AsyncAwait;

async sub get_pages ( $base, $count ) {

my @pages;

foreach my $i ( 1 .. $count ) {� push @pages, await get_page "$base/$i";� }

return @pages;�}

Syntax::Keyword::Async ?

use v5.22;

use Future::AsyncAwait;

async sub get_pages ( $base, $count ) {

my @pages;

foreach my $i ( 1 .. $count ) {� push @pages, await get_page "$base/$i";� }

return @pages;�}

12 of 49

CPAN Experiments

Modules in the newer Syntax::Operator::* space

Provide infix operators rather than prefix syntax keywords

  • Syntax::Operator::Equ
  • Syntax::Operator::In
  • Syntax::Operator::Zip

13 of 49

CPAN Experiments�Syntax::Operator::Equ

Equality comparisons that are aware of undef

use v5.38;

use Syntax::Operator::Equ;

my $str = ...;

if ( $str equ undef ) { say "Is undef"; }

elsif( $str equ "" ) { say "Is empty"; }

else { say "Is non-empty"; }

use Syntax::Operator::Equ;

"abc" equ "abc"; # true

"abc" equ "def"; # false

undef equ undef; # true

undef equ ""; # false

14 of 49

CPAN Experiments�Syntax::Operator::In

Test if an element is a member of a list

use v5.38;�use Syntax::Operator::In;��if( $n in:== (2, 3, 4) ) { say "Few items"; }

use v5.38;�use Syntax::Operator::Elem;��if( $n (2, 3, 4) ) {� say "Few items";�}

use v5.38;�use Syntax::Operator::Elem;��if( $colour elem qw( red orange yellow ) ) {� say "We like this colour";�}

in:==

in:eq

15 of 49

CPAN Experiments�Syntax::Operator::Zip

Infix operators to compose lists

use v5.38;�use Syntax::Operator::Zip;

foreach ( @epsilons Z @deltas ) {

my ( $e, $d ) = @$_;

...

}

use v5.38;�use Syntax::Operator::Zip;

foreach my ( $e, $d ) ( @epsilons M @deltas ) {

...

}

my %hash = @keys M @values;

16 of 49

CPAN Experiments�Sublike::Extended

Additional syntax for subroutine declarations

  • Named Parameters

use v5.36;

use Sublike::Extended 0.29 'sub';

sub ping ( $target, :$count )�{

...

}

ping( "foo", count => 5 );

PPC 0024

17 of 49

CPAN Experiments�Sublike::Extended

Additional syntax for subroutine declarations

  • Parameter Attributes

use v5.36;

use Sublike::Extended 0.29 'sub';

use Signature::Attribute::Alias;

sub trim ( $s :Alias )�{

$s =~ s/^\s+//;

$s =~ s/\s+$//;

}

my $str = " hello, world! ";

trim( $str );

say "<$str>";

<hello, world!>

18 of 49

CPAN Experiments�:Checked attribute

Apply value constraint assertions to subroutine parameters

use v5.36;

use Sublike::Extended 0.29 'sub';

use Signature::Attribute::Checked;

use Data::Checks qw( Num );

sub ping ( $target, :$count :Checked(Num) )�{

...

}

Named parameter :$count requires a value satisfying Num at -e line 1.

ping( "bar", count => "five" );

19 of 49

CPAN Experiments�:Checked attribute

Apply value constraint assertions to object fields

use v5.26;

use Object::Pad;

use Object::Pad::FieldAttr::Checked;

use Data::Checks qw( Num );

class Point {

field $x :Checked(Num) :param;

field $y :Checked(Num) :param;

...

}

Field $y requires a value satisfying Num at -e line 1.

Point->new( x => 10, y => "twenty" );

20 of 49

CPAN Experiments�Data::Checks

A collection of value constraint assertions

use v5.26;

use Data::Checks qw( Num );

if( Num()->check( $ARGV[0] ) ) {� say "OK";�}

else {� say "Bad";�}

$ perl check.pl 123

OK

$ perl check.pl hello

Bad

use v5.26;

use Data::Checks qw(� Num Str Object� ArrayRef HashRef Callable�);

21 of 49

CPAN Experiments�Data::Checks

A collection of value constraint assertions

use v5.26;

use Data::Checks qw( NumRange StrMatch );

NumRange(0, 100)->check( $ARGV[0] );

StrMatch(qr/a word/)->check( $ARGV[0] );

use v5.26;

use Data::Checks qw( NumRange StrEq Any );

Any(StrEq("nothing"), NumRange(0, 100))

->check( $ARGV[0] );

use v5.26;

use Data::Checks qw( NumRange StrEq );

(StrEq("nothing") | NumRange(0, 100))

->check( $ARGV[0] );

22 of 49

CPAN Experiments�Data::Checks

A collection of value constraint assertions

sub ping ( $target,� :$count :Checked(StrEq("nothing")|NumRange(0, 100))�) {

...

}

class Point {

field $x :Checked(StrEq("nothing")|NumRange(0, 100))� :param;

...

}

23 of 49

TYPES

24 of 49

CPAN Experiments�Syntax::Operator::Is

Value constraint checking as a boolean operator

use v5.26;

use Data::Checks qw( Num );

if( Num()->check( $ARGV[0] ) ) {� say "OK";�}

else {� say "Bad";�}

use v5.38;

use Syntax::Operator::Is;

use Data::Checks qw( Num );

if( $ARGV[0] is Num ) {� say "OK";�}

else {� say "Bad";�}

25 of 49

CPAN Experiments�Syntax::Operator::Is

Value constraint checking as a boolean operator

  • Operator can be renamed at import time

use v5.38;

use Test2::V0;

use Syntax::Operator::Is is => { -as => "satisfies" };

...

is( 123 satisfies Num, 'Num is testable' );

done_testing;

26 of 49

CPAN Experiments�Syntax::Keyword::Defer

Run code at scope exit

use v5.18;

use Syntax::Keyword::Defer;

my $dbh = Database->open( $path );

defer { $dbh->close; }

...

use v5.18;

use Syntax::Keyword::Try;

my $dbh;

try {

$dbh = Database->open( $path );

...

}

finally {

$dbh->close;

}

27 of 49

CPAN Experiments�Syntax::Operator::Eqr

Equality comparisons that are aware of undef and regexps

use v5.38;

use Syntax::Operator::Eqr;

my $str = ...;

if ( $str eqr undef ) { say "Is undef"; }

elsif( $str eqr "" ) { say "Is empty"; }

elsif( $str eqr qr/\d/ ) { say "Is a number"; }

else { say "Is non-empty"; }

28 of 49

CPAN Experiments

All these things possible because:

  • OP_CUSTOM 5.14
  • PL_keyword_plugin 5.14XS::Parse::Keyword
  • PL_infix_plugin 5.38XS::Parse::Infix

Core mechanisms designed to support experimentation in 3rd-party modules

29 of 49

CPAN Experiments�Easily Composable

Reflexive mechanisms in the parser

use v5.38;

use Syntax::Keyword::Match;

use Syntax::Operator::Eqr;

match( $str : eqr ) {

case( undef ) { say "Is undef"; }

case( "" ) { say "Is empty"; }

case( qr/\d/ ) { say "Is a number"; }

default { say "Is non-empty"; }

}

30 of 49

CPAN Experiments�Easily Composable

Reflexive mechanisms in the parser

use v5.38;

use Syntax::Keyword::Match;

use Syntax::Operator::Is;

use Data::Checks qw( StrEq Num );

match( $str : is ) {

case( StrEq("") ) { say "Is empty"; }

case( Num ) { say "Is a number"; }

default { say "Is non-empty"; }

}

31 of 49

CPAN Experiments�Static Grammar

Defined by data structures, not behavioural code

XPK_PARENS( /* ( EXPR : OP ) */

XPK_TERMEXPR_SCALARCTX, XPK_COLON, XPK_INFIX_MATCH_NOSMART

),

XPK_BRACES( /* { blocks... } */

XPK_REPEATED( /* case (EXPR) {BLOCK} */

XPK_COMMALIST(

XPK_KEYWORD("case"),

XPK_OPTIONAL( XPK_KEYWORD("if") ),

XPK_PARENS( XPK_TERMEXPR_SCALARCTX )

),

XPK_BLOCK

),

XPK_OPTIONAL( /* default { ... } */

XPK_KEYWORD("default"), XPK_BLOCK

)

)

32 of 49

Perl in 2030

Migrate more of those stable CPAN experiments into core

PPC process

  • Extensions of subroutine signatures (PPC0024)
  • match/case
  • any, all
  • equ, ===, eqr

33 of 49

Other Ideas

  • :void, :scalar sub attributes
  • Phaser expressions
  • More extension mechanisms

34 of 49

Other Ideas:void, :scalar sub attributes

Attributes to force the ambient context of a subroutine

use v5.36;

sub note ( $message ) {

say "Note: $message";

}

say note("before"), "middle", note("after");

$ perl ...

Note: before

Note: after

1middle1

35 of 49

Other Ideas:void, :scalar sub attributes

Attributes to force the ambient context of a subroutine

use v5.xx;

sub note :void ( $message ) {

say "Note: $message";

}

say note("before"), "middle", note("after");

$ perl ...

Note: before

Note: after

middle

36 of 49

Other Ideas�Phaser Expressions

Evaluate an expression earlier and inline a constant

use v5.10;

use constant DEBUG => $ENV{DEBUG};

if( DEBUG ) {� say "About to do the thing...";

}

use v5.xx;

if( BEGIN $ENV{DEBUG} ) {� say "About to do the thing...";

}

37 of 49

Other Ideas�Phaser Expressions

Evaluate an expression earlier and inline a constant

use v5.18;

use Syntax::Keyword::Match;

match($colour : ==) {

case(getcolour "red") { ... }

case(getcolour "green") { ... }

}

use v5.xx;

use Syntax::Keyword::Match;

match($colour : ==) {

case(BEGIN getcolour "red") { ... }

case(BEGIN getcolour "green") { ... }

}

38 of 49

Other Ideas�Errors and Warnings as Objects

More information out of them at runtime

39 of 49

Permitting More Extensibility

  • Overload v2
  • Attributes v2
  • Hooks

Allow more CPAN experimentation with more stuff

40 of 49

Permitting More Extensibility�Overload v2

Permit more kinds of operation to be overloadable

See also: overload::substr

use v5.xx;

use String::Tagged;

my $str = String::Tagged->new( "Hello, world",

message => 1,

);

my ( $word ) = $str =~ m/(\w+)/;

41 of 49

Permitting More Extensibility�Attributes v2

Interrupt the parser at compiletime

Probably to apply a Hook

Attributes in more places

Signature parameters

PPC0024� https://github.com/Perl/PPCs/blob/main/ppcs/ppc0024-signature-named-parameters.md

42 of 49

Permitting More Extensibility�Hooks

Perl has "Magic", which adds behaviour to scalar variables

struct {

int (*get) (SV *sv, MAGIC *mg);

int (*set) (SV *sv, MAGIC *mg);

int (*len) (SV *sv, MAGIC *mg);

int (*clear) (SV *sv, MAGIC *mg);

int (*free) (SV *sv, MAGIC *mg);

};

43 of 49

Permitting More Extensibility�Hooks

Magic is both "too much" and "too little"

Magic as side-annotations

free, maybe dup

Special-cases in perl core

overload, tie, vstring, ...

44 of 49

Permitting More Extensibility�Hooks

Hierarchy of shapes

struct BaseHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook *hk);

int (*clone) (SV *osv, SV *nsv, Hook *hk,� CLONE_PARAMS *params);

};

struct ValueHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook*hk);

int (*clone) (SV *osv, SV *nsv, ...

int (*copy) (SV *osv, SV *nsv, Hook *hk);

};

struct ScalarHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook*hk);

int (*clone) (SV *osv, SV *nsv, ...

int (*get) (SV *sv, Hook *hk);

int (*set) (SV *sv, Hook *hk);

int (*clear) (SV *sv, Hook *hk);

};

45 of 49

Permitting More Extensibility�Hooks

Extend the behaviour of things that aren't just scalar variables

struct ArrayHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook*hk);

int (*clone) (SV *osv, SV *nsv, ...

...

};

struct HashHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook*hk);

int (*clone) (SV *osv, SV *nsv, ...

...

};

struct CodeHook {

U32 ver;

U32 flags;

int (*free) (SV *sv, Hook*hk);

int (*clone) (SV *osv, SV *nsv, ...

...

};

46 of 49

See Also

47 of 49

See Also

CPAN:

Data::Checks

Future::AsyncAwait

List::Keywords

Object::Pad

Object::Pad::FieldAttr::Checked

Signature::Attribute::Checked

Sublike::Extended

Syntax::Keyword::Defer

Syntax::Keyword::Match

Syntax::Keyword::Try

Syntax::Operator::Equ

Syntax::Operator::Eqr

Syntax::Operator::In

Syntax::Operator::Is

Syntax::Operator::Zip

48 of 49

Thank You

Questions?

49 of 49

NO