Modern-Perl

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for Modern::Perl

1.20250607 2025-06-07 16:56:19-07:00 America/Los_Angeles
    - update for 2025 year bundle
    - enhance documentation to discourage this module for v5.38 and newer

1.20241001 2024-09-30 19:12:47-07:00 America/Los_Angeles
    - fix switch tests after Perl 5.41.4 removal of deprecated feature (RT #155822, Slaven Rezic)

1.20240120 2024-01-20 12:15:09-08:00 America/Los_Angeles
    - fix tests for Perl < 5.26.0 (RT #151198, Slaven Rezic)

Changes  view on Meta::CPAN

    - fix tests for Perl 5.32 (Tony Cook, RT #131608)
    - update for 2020

1.20190727 2019-07-27 12:15:27-07:00 America/Los_Angeles
    - remove explicit autodie dependency (GH #11, gordon-fish, mst, #perl)
    - add description of odern::Perl module (Utkarsh Gupta, Debian, GH issue #12)

1.20190601 2019-06-01 09:19:36-07:00 America/Los_Angeles
    - update for 2019
    - reduce scope of lexical %dates (RT #128406)
    - support `perl -Modern::Perl=20xx` (RT #96319)

1.20181021 2018-10-21 12:09:32-07:00 America/Los_Angeles
    - autogenerate META.json file (Mohammad S Anwar, GH PR #7)
    - remove Module::Build build dependency to make installation easier

1.20180928 2018-09-27 18:29:25-07:00 America/Los_Angeles
    - skip tests for Perls without arraybase (Dagfinn Ilmari Mannsåker, GH #10)

1.20180901 2018-09-01 12:19:53-07:00 America/Los_Angeles
    - skip tests when PERL5OPT is set (David Precious, GH #9)

Makefile.PL  view on Meta::CPAN


my %WriteMakefileArgs = (
  "ABSTRACT" => "enable all of the features of Modern Perl with one import",
  "AUTHOR" => "chromatic",
  "CONFIGURE_REQUIRES" => {
    "ExtUtils::MakeMaker" => 0
  },
  "DISTNAME" => "Modern-Perl",
  "LICENSE" => "perl",
  "MIN_PERL_VERSION" => "5.010",
  "NAME" => "Modern::Perl",
  "PREREQ_PM" => {
    "IO::File" => 0,
    "IO::Handle" => 0,
    "feature" => 0,
    "mro" => 0,
    "strict" => 0,
    "warnings" => 0
  },
  "TEST_REQUIRES" => {
    "Cwd" => 0,

README  view on Meta::CPAN

Modern::Perl
------------

Modern Perl often relies on the presence of several core and CPAN pragmas and
modules.  Wouldn't it be nice to use them all with a single command?  Try this
one:

    use Modern::Perl;

*NOTE* that Perl versions 5.38 and newer effectively do the same thing with:

    use v5.38; # or v5.40, v5.42, etc

... so if you're writing code with those language versions, you may not need
this module at all!

INSTALLATION

README  view on Meta::CPAN

    $ perl Build.PL
    $ perl ./Build
    $ perl ./Build test
    $ sudo perl ./Build install

SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

    perldoc Modern::Perl

You can also look for information at:

    RT, CPAN's request tracker
        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Modern-Perl

    AnnoCPAN, Annotated CPAN documentation
        http://annocpan.org/dist/Modern-Perl

    CPAN Ratings

lib/Modern/Perl.pm  view on Meta::CPAN

package Modern::Perl;
# ABSTRACT: enable all of the features of Modern Perl with one import
$Modern::Perl::VERSION = '1.20250607';
use 5.010_000;

use strict;
use warnings;

use mro     ();
use feature ();

# enable methods on filehandles; unnecessary when 5.14 autoloads them
use IO::File   ();
use IO::Handle ();

my $wanted_date;

sub VERSION {
    my ($self, $version) = @_;

    my $default = 2025;

    return $Modern::Perl::VERSION || $default unless defined $version;
    return $Modern::Perl::VERSION || $default if             $version < 2009;

    $wanted_date = $version if (caller(1))[3] =~ /::BEGIN/;
    return $default;
}

my $unimport_tag;
BEGIN {
    $unimport_tag = $] > 5.015 ? ':all' : ':5.10';
}

lib/Modern/Perl.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Modern::Perl - enable all of the features of Modern Perl with one import

=head1 VERSION

version 1.20250607

=head1 SYNOPSIS

Modern Perl programs use several modules to enable additional features of Perl
and of the CPAN.  Instead of copying and pasting all of these C<use> lines,
instead write only one:

    use Modern::Perl;

This enables the L<strict> and L<warnings> pragmas, as well as all of the
features available in Perl 5.10. It also enables C3 method resolution order as
documented in C<perldoc mro> and loads L<IO::File> and L<IO::Handle> so that
you may call methods on filehandles. In the future, it may include additional
core modules and pragmas (but is unlikely to include non-core features).

Because so much of this module's behavior uses lexically scoped pragmas, you
may disable these pragmas within an inner scope with:

    no Modern::Perl;

See L<http://www.modernperlbooks.com/mt/2009/01/toward-a-modernperl.html> for
more information, L<http://www.modernperlbooks.com/> for further discussion of
Modern Perl and its implications, and
L<http://onyxneon.com/books/modern_perl/index.html> for a freely-downloadable
Modern Perl tutorial.

=head2 CLI Usage

As of Modern::Perl 2019, you may also enable this pragma from the command line:

    $ perl -Modern::Perl -e 'say "Take that, awk!"'

You may also enable year-specific features:

    $ perl -Modern::Perl=2020 -e 'say "Looking forward to Perl 5.30!"'

=head2 Wrapping Modern::Perl

If you want to wrap Modern::Perl in your own C<import()> method, you can do so
to add additional pragmas or features, such as the use of L<Try::Tiny>. Please
note that, if you do so, you will I<not> automatically enable C3 method
resolution in the calling scope. This is due to how the L<mro> pragma works. In
your custom C<import()> method, you will need to write code such as:

    mro::set_mro( scalar caller(), 'c3' );

=head2 Forward Compatibility

For forward compatibility, I recommend you specify a string containing a
I<year> value as the single optional import tag. For example:

    use Modern::Perl '2009';
    use Modern::Perl '2010';

... both enable 5.10 features, while:

    use Modern::Perl '2011';

... enables 5.12 features:

    use Modern::Perl '2012';

... enables 5.14 features:

    use Modern::Perl '2013';

... enables 5.16 features, and:

    use Modern::Perl '2014';

... enables 5.18 features, and:

    use Modern::Perl '2015';

... enables 5.20 features, and:

    use Modern::Perl '2016';

... enables 5.24 features, and:

    use Modern::Perl '2017';

... enables 5.24 features, and:

    use Modern::Perl '2018';

... enables 5.26 features, and:

    use Modern::Perl '2019';

... enables 5.28 features, and:

    use Modern::Perl '2020';

... enables 5.30 features, and:

    use Modern::Perl '2021';

... enables 5.32 features, and:

    use Modern::Perl '2022';

... enables 5.34 features, and:

    use Modern::Perl '2023';

... enables 5.36 features, and:

    use Modern::Perl '2024';

... enables 5.38 features, and:

    use Modern::Perl '2025';

... enables 5.40 features.

Obviously you cannot use newer features on earlier versions. Perl will throw
the appropriate exception if you try.

As of Perl 5.38, you may prefer to write C<use v5.38>, which is almost entirely
equivalent to the use of this module. For the purpose of forward compatibility,
this module will continue to work as expected--and will continue regular
maintenance.

lib/Modern/Perl.pm  view on Meta::CPAN

Please report any bugs or feature requests to C<bug-modern-perl at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Modern-Perl>.  I will be
notified, and then you'll automatically be notified of progress on your bug as
I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Modern::Perl

You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Modern-Perl>

=item * AnnoCPAN: Annotated CPAN documentation

lib/odern/Perl.pm  view on Meta::CPAN

package odern::Perl;
#ABSTRACT: Module for enabling all of the features of Modern Perl
$odern::Perl::VERSION = '1.20250607';
use Modern::Perl;

*import = \&Modern::Perl::import;

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

t/base.t  view on Meta::CPAN

#! perl

use Test::More 0.98;

BEGIN
{
    delete $INC{'IO/File.pm'};
    delete $INC{'IO/Handle.pm'};

    use_ok( 'Modern::Perl' ) or exit;
    ok $INC{'IO/File.pm'},   'M::P should load IO::File';
    ok $INC{'IO/Handle.pm'}, 'M::P should load IO::Handle';

    Modern::Perl->import();
}

eval 'say "# say() should be available";';
is( $@, '', 'say() should be available' );

eval '$x = 1;';
like( $@, qr/Global symbol "\$x" requires explicit/,
    'strict should be enabled' );

my $warnings;

t/base.t  view on Meta::CPAN

package B;

@B::ISA = 'A';

package C;

@C::ISA = 'A';

package D;

use Modern::Perl;

@D::ISA = qw( B C );

END_CLASSES

package main;

is_deeply( mro::get_linear_isa( 'D' ), [qw( D B C A )], 'mro should use C3' );

if ($] > 5.011003)
{
    eval q|
    use Modern::Perl;
    BEGIN
    {
      ok exists $^H{feature_unicode},
        '... and should unilaterally enable unicode_strings, when available';
    }
    |;
}

done_testing;

t/regressions.t  view on Meta::CPAN

#! perl

use Test::More 0.98;

use Modern::Perl ();

if ($ENV{PERL5OPT}) {
    plan( skip_all => "Cannot reliably test with PERL5OPT set" );
    exit 0;
}

$SIG{__WARN__} = sub
{
    return if $_[0] =~ /Number found where operator expected/;
    return if $_[0] =~ /Do you need to predeclare/;
    return if $_[0] =~ /future reserved word/;
    return if $_[0] =~ /given is (experimental|deprecated)/;
    warn shift
};

eval 'sub { given (0) {} }';
isnt $@, '', 'use Modern::Perl () does not enable switch';
eval 'sub { say 0 }';
isnt $@, '', 'use Modern::Perl () does not enable say';
eval 'state $x;';
isnt $@, '', 'use Modern::Perl () does not enable state';
is uc "\xdf", "\xdf", 'Modern::Perl () does not enable unicode_strings';

sub test_switch {
    my $version = shift;
    return if $] >= 5.041004;
    eval "use Modern::Perl $version; sub { given (0) {} }";
    is $@, '', qq|use Modern::Perl $version enables switch|;
}

{
    use Modern::Perl 2009;
    eval 'sub { say 0 }';
    test_switch(2009);
    is $@, '', q|use Modern::Perl 2009 enables say|;
    eval 'state $x';
    is $@, '', q|use Modern::Perl 2009 enables state|;
    is uc "\xdf", "\xdf", 'but not unicode_strings';
}

{
    use Modern::Perl 2010;
    test_switch(2010);
    eval 'sub { say 0 }';
    is $@, '', q|use Modern::Perl 2010 enables say|;
    eval 'state $x';
    is $@, '', q|use Modern::Perl 2010 enables state|;
    is uc "\xdf", "\xdf", 'but not unicode_strings';
}

if ($] >= 5.012)
{
    eval <<'END_HERE';
    use Modern::Perl 2011;
    test_switch(2011);
    eval 'sub { say 0 }';
    is $@, '', q|use Modern::Perl 2011 enables say|;
    eval 'state $x';
    is $@, '', q|use Modern::Perl 2011 enables state|;
    is uc "\xdf", "SS", '2011 enables unicode_strings';
END_HERE
}

if ($] >= 5.014)
{
    eval <<'END_HERE';
    use Modern::Perl 2012;
    test_switch(2012);
    eval 'sub { say 0 }';
    is $@, '', q|use Modern::Perl 2012 enables say|;
    eval 'state $x';
    is $@, '', q|use Modern::Perl 2012 enables state|;
    is uc "\xdf", "SS", '2012 enables unicode_strings';
END_HERE
}

eval 'sub { given (0) {} }';
isnt $@, "", 'switch feature does not leak out';
eval 'sub { say 0 }';
isnt $@, '', 'say feature does not leak out';
eval 'state $x';
isnt $@, '', 'state feature does not leak out';
is uc "\xdf", "\xdf", 'unicode_strings feature does not leak out';


# RT #80304: warning on Modern::Perl->VERSION()
{
    my    $warning           = '';
    local $SIG{__WARN__}     = sub { $warning = shift };
    $Modern::Perl::VERSION ||= '1.20121103';

    my   $version            = Modern::Perl->VERSION;
    like $version, qr/1\.20\d/,
        'VERSION() should return version number, given no argument';
    is $warning, '', '... without warning about undef argument';
}

done_testing;

t/unimport.t  view on Meta::CPAN

#! perl

use Test::More 0.98;
use Modern::Perl;

if ($ENV{PERL5OPT}) {
    plan( skip_all => "Cannot reliably test with PERL5OPT set" );
    exit 0;
}

eval 'say "# say() should be available";';
is $@, '', 'say() should be available';

{
    no Modern::Perl;
    eval 'say "# say() should be unavailable when unimported"';
    like $@, qr/syntax error.+near "say /,
        'unimport should disable say feature';
    eval '$x = 1';
    is $@, '', 'unimport should disable strictures';

    my $warnings;
    local $SIG{__WARN__} = sub { $warnings = shift };
    my $y =~ s/hi//;
    unlike $warnings, qr/Use of uninitialized value/,

t/year_imports.t  view on Meta::CPAN

#! perl

use Test::More 0.98;

use Modern::Perl ();
use Cwd;
use File::Spec;

if ($ENV{PERL5OPT}) {
    plan( skip_all => "Cannot reliably test with PERL5OPT set" );
    exit 0;
}

$SIG{__WARN__} = sub
{

t/year_imports.t  view on Meta::CPAN

    my $year = shift;
    return $year eq '()' ? $year : "'$year'";
}

sub test_lexical_subs_for
{
    # lexical subs removed from feature.pm in 5.25.2
    return if $] >= 5.025002;

    my $year = _get_year(shift);
    eval qq|use Modern::Perl $year; my sub foo {}|;
    isnt $@, '', qq|use Modern::Perl $year should not enable lexical subs|;
}

sub test_switch_for {
    # given removed in 5.41.4
    return if $] >= 5.041004;

    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; sub { given (0) {} }|;
    is $@, '', qq|use Modern::Perl $year enables switch|;
}

sub test_no_switch_for {
    # given removed in 5.41.4
    return if $] >= 5.041004;

    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; sub { given (0) {} }|;
    isnt $@, '', qq|use Modern::Perl $year does not enable switch|;
}

sub test_no_indirect_for {
    my $year = _get_year(shift);

    my $warning = '';
    local $SIG{__WARN__} = sub { $warning = shift };

    eval qq|use Modern::Perl $year; my \$foo = new Modern::Perl;|;
    like $@, qr/syntax error.+near "new Modern::Perl"/,
        qq|use Modern::Perl $year disables indirect method calls|;
}

sub test_no_multidimensional_for {
    my $year = _get_year(shift);

    my $warning = '';
    local $SIG{__WARN__} = sub { $warning = shift };

    eval qq{
        use Modern::Perl $year;
        my (\$x, \$y) = (1, 2);
        my %foo;

        \$foo{\$x, \$y} = 'bar';
    };
    like $@, qr/Multidimensional hash lookup is disabled/,
        qq|use Modern::Perl $year disables multidimensional array emulation|;
}

sub test_say_for {
    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; sub { say 0 }|;
    is $@, '', qq|use Modern::Perl $year enables say|;
}

sub test_state_for {
    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; state \$x;|;
    is $@, '', qq|use Modern::Perl $year enables state|;
}

sub test_cur_sub_for {
    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; sub { return __SUB__ }|;
    is $@, '', qq|use Modern::Perl $year enables current_sub|;
}

sub test_array_base_for {
    my $year = _get_year(shift);

    my $warning = '';
    local $SIG{__WARN__} = sub { $warning = shift };

    if (eval qq|use Modern::Perl $year; \$[ = 10|) {
        like $warning, qr/Use of assignment to \$\[ is deprecated/,
            qq|use Modern::Perl $year disables array_base|;
    }
    else {
        like $@, qr/Assigning non-zero to \$\[ is no longer possible/,
            qq|use Modern::Perl $year works without array_base|;
    }
}

sub test_fc_for {
    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; fc("tschüß") eq fc("TSCHÜSS")|;
    is $@, '', qq|use Modern::Perl $year enables fc|;
}

sub test_postderef_for {
    my $year = _get_year(shift);

    eval qq|use Modern::Perl $year; my \$r = [ 1, [ 2, 3 ], 4 ]; \$r->[1]->@*|;
    is $@, '', qq|use Modern::Perl $year enables postderef_qq|;
}

sub test_unicode_strings_for {
    my $year = _get_year(shift);

    eval qq{
        use Modern::Perl $year;
        is uc "\xdf", "SS", q|use Modern::Perl $year enables unicode_strings|;
    };
}

sub test_signatures_for {
    my $year = _get_year(shift);

    my @warnings;
    local $SIG{__WARN__} = sub { push @warnings, @_ };

    local $@;
    my ($yearnum) = $year =~ m/(\d+)/;
    eval qq{
        use Modern::Perl $year;
        sub foo_$yearnum( \$bar ) { ... }
    };
    is $@, '', qq|use Modern::Perl $year enables signatures|;
    is @warnings, 0, '... and disables signature warnings';
}

sub test_isa_for {
    my $year = _get_year(shift);

    eval qq{
        use Modern::Perl $year;
        my \$foo = bless {}, 'Some::Class';
        my \$result = \$foo isa 'Some::Class';
    };
    is $@, '', qq|use Modern::Perl $year enables isa|;
}

sub test_warnings_for {
    my $year = _get_year(shift);

    my $warnings;

    local $SIG{__WARN__} = sub { $warnings = shift };

    eval qq{
        no warnings;
        use Modern::Perl $year;
        my \$x = "2:" + 3;
    };

    like $warnings, qr/Argument "2:" isn't numeric/, qq|use Modern::Perl $year enables warnings|;
}

sub test_module_true_for {
    my $year   = _get_year(shift);
    my $cwd    = Cwd::cwd();
    my $tmpdir = File::Spec->tmpdir;

    chdir $tmpdir;

    open my $fh, '>', 'Foo.pm'
        or die "Cannot write 'Foo.pm': $!\n";

    # don't use <<~ heredoc to trim whitespace
    # as this will fail with Perl < 5.26
    # see RT #151189
    $fh->print(<<EOF);
package Foo;

use Modern::Perl $year;

sub bar { 'returned from Foo::bar()' }

return 0;
EOF
    close $fh;

    local @INC = '.';

    my $result;
    eval qq{
        use Foo;
        \$result = Foo->bar;
    };

    is $result, 'returned from Foo::bar()',
        qq|use Modern::Perl $year enables module_true|;

    chdir $cwd;
}

eval 'sub { given (0) {} }';
isnt $@, '', 'use Modern::Perl () does not enable switch';

eval 'sub { say 0 }';
isnt $@, '', 'use Modern::Perl () does not enable say';

eval 'state $x;';
isnt $@, '', 'use Modern::Perl () does not enable state';
is uc "\xdf", "\xdf", 'Modern::Perl () does not enable unicode_strings';

eval 'sub { return __SUB__ }';
is $@, '', q|use Modern::Perl '2013' does not enable current_sub|;

{
    my $warning = '';
    local $SIG{__WARN__} = sub { $warning = shift };
    eval 'fc("tschüß") eq fc("TSCHÜSS")';
    isnt $@, '', q|use Modern::Perl () does not enable fc|;
}

{
    use Modern::Perl '2009';

    test_switch_for( '2009' );
    test_say_for(    '2009' );
    test_state_for(  '2009' );

    is uc "\xdf", "\xdf", q|use Modern::Perl '2009' does not enable unicode_strings|;
}

{
    use Modern::Perl '2010';

    test_switch_for( '2010' );
    test_say_for(    '2010' );
    test_state_for(  '2010' );

    is uc "\xdf", "\xdf", q|use Modern::Perl '2010' does not enable unicode_strings|;
}

if ($] >= 5.012)
{
    my $year = 2011;

    test_switch_for(          $year );
    test_say_for(             $year );
    test_state_for(           $year );
    test_unicode_strings_for( $year );



( run in 0.302 second using v1.01-cache-2.11-cpan-4d50c553e7e )