├── .gitignore ├── lib ├── odern │ └── Perl.pm └── Modern │ └── Perl.pm ├── t ├── odern.t ├── unimport.t ├── base.t ├── regressions.t └── year_imports.t ├── dist.ini ├── README └── Changes /.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | META.yml 3 | Modern-Perl-*/ 4 | Modern-Perl-*.tar.gz 5 | .prove 6 | .build/ 7 | -------------------------------------------------------------------------------- /lib/odern/Perl.pm: -------------------------------------------------------------------------------- 1 | package odern::Perl; 2 | #ABSTRACT: Module for enabling all of the features of Modern Perl 3 | 4 | use Modern::Perl; 5 | 6 | *import = \&Modern::Perl::import; 7 | 8 | 1; 9 | -------------------------------------------------------------------------------- /t/odern.t: -------------------------------------------------------------------------------- 1 | #! perl 2 | 3 | use Test::More; 4 | 5 | use odern::Perl (); 6 | 7 | { 8 | eval "use odern::Perl; sub say { 0 }"; 9 | is $@, "", 'use odern::Perl enables say'; 10 | } 11 | 12 | { 13 | eval "use odern::Perl '3030'; ok( 0 )"; 14 | like $@, qr/Unknown date '3030' requested/, 15 | q|use odern::Perl '3030' throws year error|; 16 | } 17 | 18 | done_testing; 19 | -------------------------------------------------------------------------------- /t/unimport.t: -------------------------------------------------------------------------------- 1 | #! perl 2 | 3 | use Test::More 0.98; 4 | use Modern::Perl; 5 | 6 | if ($ENV{PERL5OPT}) { 7 | plan( skip_all => "Cannot reliably test with PERL5OPT set" ); 8 | exit 0; 9 | } 10 | 11 | eval 'say "# say() should be available";'; 12 | is $@, '', 'say() should be available'; 13 | 14 | { 15 | no Modern::Perl; 16 | eval 'say "# say() should be unavailable when unimported"'; 17 | like $@, qr/syntax error.+near "say /, 18 | 'unimport should disable say feature'; 19 | eval '$x = 1'; 20 | is $@, '', 'unimport should disable strictures'; 21 | 22 | my $warnings; 23 | local $SIG{__WARN__} = sub { $warnings = shift }; 24 | my $y =~ s/hi//; 25 | unlike $warnings, qr/Use of uninitialized value/, 26 | 'unimport should disable warnings'; 27 | } 28 | 29 | done_testing; 30 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name = Modern-Perl 2 | author = chromatic 3 | license = Perl_5 4 | copyright_holder = chromatic@wgz.org 5 | copyright_year = 2025 6 | 7 | [AutoVersion] 8 | format = {{ cldr('1.yyyyMMdd') }} 9 | 10 | [AutoPrereqs] 11 | 12 | [Prereqs] 13 | perl = 5.010 14 | 15 | [@Filter] 16 | -bundle = @Basic 17 | -remove = Readme 18 | 19 | [PodWeaver] 20 | finder = :InstallModules 21 | 22 | [PkgVersion] 23 | [PodVersion] 24 | [NextRelease] 25 | [MetaJSON] 26 | 27 | [@Git] 28 | changelog = Changes ; this is the default 29 | allow_dirty = dist.ini ; see Git::Check... 30 | allow_dirty = Changes ; ... and Git::Commit 31 | commit_msg = v%v%n%n%c ; see Git::Commit 32 | tag_format = %v ; see Git::Tag 33 | tag_message = %v ; see Git::Tag 34 | push_to = origin ; see Git::Push 35 | 36 | [MetaResources] 37 | homepage = https://github.com/chromatic/Modern-Perl 38 | repository.url = https://github.com/chromatic/Modern-Perl.git 39 | repository.web = https://github.com/chromatic/Modern-Perl 40 | repository.type = git 41 | -------------------------------------------------------------------------------- /t/base.t: -------------------------------------------------------------------------------- 1 | #! perl 2 | 3 | use Test::More 0.98; 4 | 5 | BEGIN 6 | { 7 | delete $INC{'IO/File.pm'}; 8 | delete $INC{'IO/Handle.pm'}; 9 | 10 | use_ok( 'Modern::Perl' ) or exit; 11 | ok $INC{'IO/File.pm'}, 'M::P should load IO::File'; 12 | ok $INC{'IO/Handle.pm'}, 'M::P should load IO::Handle'; 13 | 14 | Modern::Perl->import(); 15 | } 16 | 17 | eval 'say "# say() should be available";'; 18 | is( $@, '', 'say() should be available' ); 19 | 20 | eval '$x = 1;'; 21 | like( $@, qr/Global symbol "\$x" requires explicit/, 22 | 'strict should be enabled' ); 23 | 24 | my $warnings; 25 | local $SIG{__WARN__} = sub { $warnings = shift }; 26 | my $y =~ s/hi//; 27 | like( $warnings, qr/Use of uninitialized value/, 'warnings should be enabled' ); 28 | 29 | eval<<'END_CLASSES'; 30 | 31 | package A; 32 | 33 | $A::VERSION = 1; 34 | 35 | package B; 36 | 37 | @B::ISA = 'A'; 38 | 39 | package C; 40 | 41 | @C::ISA = 'A'; 42 | 43 | package D; 44 | 45 | use Modern::Perl; 46 | 47 | @D::ISA = qw( B C ); 48 | 49 | END_CLASSES 50 | 51 | package main; 52 | 53 | is_deeply( mro::get_linear_isa( 'D' ), [qw( D B C A )], 'mro should use C3' ); 54 | 55 | if ($] > 5.011003) 56 | { 57 | eval q| 58 | use Modern::Perl; 59 | BEGIN 60 | { 61 | ok exists $^H{feature_unicode}, 62 | '... and should unilaterally enable unicode_strings, when available'; 63 | } 64 | |; 65 | } 66 | 67 | done_testing; 68 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Modern::Perl 2 | ------------ 3 | 4 | Modern Perl often relies on the presence of several core and CPAN pragmas and 5 | modules. Wouldn't it be nice to use them all with a single command? Try this 6 | one: 7 | 8 | use Modern::Perl; 9 | 10 | *NOTE* that Perl versions 5.38 and newer effectively do the same thing with: 11 | 12 | use v5.38; # or v5.40, v5.42, etc 13 | 14 | ... so if you're writing code with those language versions, you may not need 15 | this module at all! 16 | 17 | INSTALLATION 18 | 19 | To install this module, run the following commands: 20 | 21 | $ perl Build.PL 22 | $ perl ./Build 23 | $ perl ./Build test 24 | $ sudo perl ./Build install 25 | 26 | SUPPORT AND DOCUMENTATION 27 | 28 | After installing, you can find documentation for this module with the 29 | perldoc command. 30 | 31 | perldoc Modern::Perl 32 | 33 | You can also look for information at: 34 | 35 | RT, CPAN's request tracker 36 | http://rt.cpan.org/NoAuth/Bugs.html?Dist=Modern-Perl 37 | 38 | AnnoCPAN, Annotated CPAN documentation 39 | http://annocpan.org/dist/Modern-Perl 40 | 41 | CPAN Ratings 42 | http://cpanratings.perl.org/d/Modern-Perl 43 | 44 | Search CPAN 45 | http://search.cpan.org/dist/Modern-Perl/ 46 | 47 | 48 | COPYRIGHT AND LICENCE 49 | 50 | Copyright (C) 2009-2025 chromatic 51 | 52 | This program is free software; you can redistribute it and/or modify it 53 | under the same terms as Perl itself. 54 | -------------------------------------------------------------------------------- /t/regressions.t: -------------------------------------------------------------------------------- 1 | #! perl 2 | 3 | use Test::More 0.98; 4 | 5 | use Modern::Perl (); 6 | 7 | if ($ENV{PERL5OPT}) { 8 | plan( skip_all => "Cannot reliably test with PERL5OPT set" ); 9 | exit 0; 10 | } 11 | 12 | $SIG{__WARN__} = sub 13 | { 14 | return if $_[0] =~ /Number found where operator expected/; 15 | return if $_[0] =~ /Do you need to predeclare/; 16 | return if $_[0] =~ /future reserved word/; 17 | return if $_[0] =~ /given is (experimental|deprecated)/; 18 | warn shift 19 | }; 20 | 21 | eval 'sub { given (0) {} }'; 22 | isnt $@, '', 'use Modern::Perl () does not enable switch'; 23 | eval 'sub { say 0 }'; 24 | isnt $@, '', 'use Modern::Perl () does not enable say'; 25 | eval 'state $x;'; 26 | isnt $@, '', 'use Modern::Perl () does not enable state'; 27 | is uc "\xdf", "\xdf", 'Modern::Perl () does not enable unicode_strings'; 28 | 29 | sub test_switch { 30 | my $version = shift; 31 | return if $] >= 5.041004; 32 | eval "use Modern::Perl $version; sub { given (0) {} }"; 33 | is $@, '', qq|use Modern::Perl $version enables switch|; 34 | } 35 | 36 | { 37 | use Modern::Perl 2009; 38 | eval 'sub { say 0 }'; 39 | test_switch(2009); 40 | is $@, '', q|use Modern::Perl 2009 enables say|; 41 | eval 'state $x'; 42 | is $@, '', q|use Modern::Perl 2009 enables state|; 43 | is uc "\xdf", "\xdf", 'but not unicode_strings'; 44 | } 45 | 46 | { 47 | use Modern::Perl 2010; 48 | test_switch(2010); 49 | eval 'sub { say 0 }'; 50 | is $@, '', q|use Modern::Perl 2010 enables say|; 51 | eval 'state $x'; 52 | is $@, '', q|use Modern::Perl 2010 enables state|; 53 | is uc "\xdf", "\xdf", 'but not unicode_strings'; 54 | } 55 | 56 | if ($] >= 5.012) 57 | { 58 | eval <<'END_HERE'; 59 | use Modern::Perl 2011; 60 | test_switch(2011); 61 | eval 'sub { say 0 }'; 62 | is $@, '', q|use Modern::Perl 2011 enables say|; 63 | eval 'state $x'; 64 | is $@, '', q|use Modern::Perl 2011 enables state|; 65 | is uc "\xdf", "SS", '2011 enables unicode_strings'; 66 | END_HERE 67 | } 68 | 69 | if ($] >= 5.014) 70 | { 71 | eval <<'END_HERE'; 72 | use Modern::Perl 2012; 73 | test_switch(2012); 74 | eval 'sub { say 0 }'; 75 | is $@, '', q|use Modern::Perl 2012 enables say|; 76 | eval 'state $x'; 77 | is $@, '', q|use Modern::Perl 2012 enables state|; 78 | is uc "\xdf", "SS", '2012 enables unicode_strings'; 79 | END_HERE 80 | } 81 | 82 | eval 'sub { given (0) {} }'; 83 | isnt $@, "", 'switch feature does not leak out'; 84 | eval 'sub { say 0 }'; 85 | isnt $@, '', 'say feature does not leak out'; 86 | eval 'state $x'; 87 | isnt $@, '', 'state feature does not leak out'; 88 | is uc "\xdf", "\xdf", 'unicode_strings feature does not leak out'; 89 | 90 | 91 | # RT #80304: warning on Modern::Perl->VERSION() 92 | { 93 | my $warning = ''; 94 | local $SIG{__WARN__} = sub { $warning = shift }; 95 | $Modern::Perl::VERSION ||= '1.20121103'; 96 | 97 | my $version = Modern::Perl->VERSION; 98 | like $version, qr/1\.20\d/, 99 | 'VERSION() should return version number, given no argument'; 100 | is $warning, '', '... without warning about undef argument'; 101 | } 102 | 103 | done_testing; 104 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for Modern::Perl 2 | 3 | {{$NEXT}} 4 | 5 | 1.20250607 2025-06-07 16:56:19-07:00 America/Los_Angeles 6 | - update for 2025 year bundle 7 | - enhance documentation to discourage this module for v5.38 and newer 8 | 9 | 1.20241001 2024-09-30 19:12:47-07:00 America/Los_Angeles 10 | - fix switch tests after Perl 5.41.4 removal of deprecated feature (RT #155822, Slaven Rezic) 11 | 12 | 1.20240120 2024-01-20 12:15:09-08:00 America/Los_Angeles 13 | - fix tests for Perl < 5.26.0 (RT #151198, Slaven Rezic) 14 | - fix feature reset for Perl < 5.15 (RT #151190, Slaven Rezic) 15 | 16 | 1.20240115 2024-01-14 17:47:22-08:00 America/Los_Angeles 17 | - update for 2024 year bundle 18 | 19 | 1.20230106 2023-01-05 17:15:46-08:00 America/Los_Angeles 20 | - update for 2023 year bundle 21 | - fix a few nits in tests 22 | 23 | 1.20220515 2022-05-15 11:15:25-07:00 America/Los_Angeles 24 | - enable signatures in 2022 year bundle 25 | - add 2021 and 2022 year bundles 26 | 27 | 1.20200211 2020-02-10 19:33:55-08:00 America/Los_Angeles 28 | - bash doesn't like !' in double quotes, so it stuck up for awk 29 | 30 | 1.20200201 2020-01-31 18:41:36-08:00 America/Los_Angeles 31 | - fix tests for Perl 5.32 (Tony Cook, RT #131608) 32 | - update for 2020 33 | 34 | 1.20190727 2019-07-27 12:15:27-07:00 America/Los_Angeles 35 | - remove explicit autodie dependency (GH #11, gordon-fish, mst, #perl) 36 | - add description of odern::Perl module (Utkarsh Gupta, Debian, GH issue #12) 37 | 38 | 1.20190601 2019-06-01 09:19:36-07:00 America/Los_Angeles 39 | - update for 2019 40 | - reduce scope of lexical %dates (RT #128406) 41 | - support `perl -Modern::Perl=20xx` (RT #96319) 42 | 43 | 1.20181021 2018-10-21 12:09:32-07:00 America/Los_Angeles 44 | - autogenerate META.json file (Mohammad S Anwar, GH PR #7) 45 | - remove Module::Build build dependency to make installation easier 46 | 47 | 1.20180928 2018-09-27 18:29:25-07:00 America/Los_Angeles 48 | - skip tests for Perls without arraybase (Dagfinn Ilmari Mannsåker, GH #10) 49 | 50 | 1.20180901 2018-09-01 12:19:53-07:00 America/Los_Angeles 51 | - skip tests when PERL5OPT is set (David Precious, GH #9) 52 | 53 | 1.20180701 2018-07-01 10:34:32-07:00 America/Los_Angeles 54 | - added support for Perl 5.26 and 5.28 55 | 56 | 1.20170117 2017-01-16 20:37:12-08:00 America/Los_Angeles 57 | - cleaned up test suite 58 | - fixed Perl 5.25 failures (RT #114690) 59 | 60 | 1.20170116 2017-01-16 08:46:50-08:00 America/Los_Angeles 61 | - updated for 2017 release 62 | - maybe 2016 should have supported 5.22, but given how long I waited... oops 63 | - improved documentation about reexporting (RT #109076) 64 | 65 | 1.20161229 2016-12-28 16:02:17-08:00 America/Los_Angeles 66 | - improved VERSION numbering (Gryphon Shafer, GH #5) 67 | 68 | 1.20161005 2016-10-05 09:38:21-07:00 America/Los_Angeles 69 | - updated for 2016 release (Gryphon Shafer) 70 | - added support for 5.24 71 | 72 | 1.20150127 2015-01-26 23:21:44-08:00 America/Los_Angeles 73 | - updated for 2015 release (Elmer Quintanilla) 74 | - added support for 5.20 75 | 76 | 1.20140107 2014-01-07 15:35:42 America/Los_Angeles 77 | - updated for 2014 release 78 | - added support for 5.18 79 | 80 | 1.20121103 2012-11-03 13:30:26 America/Los_Angeles 81 | - fixed VERSION( undef ) (Peter Vereshagin, RT #80304) 82 | - fixed POD encoding error (Norbert E. Grüner, RT #80468) 83 | 84 | 1.20120521 2012-05-21 15:58:59 America/Los_Angeles 85 | - added Perl 5.16 support 86 | 87 | 1.20120130 2012-01-30 11:38:08 America/Los_Angeles 88 | - fixed t/year_imports.t for 5.10 (ANDK and sprout again) 89 | 90 | 1.20120126 2012-01-25 22:15:50 America/Los_Angeles 91 | - fixed t/regressions.t for 5.10 92 | 93 | 1.20120123 2012-01-23 10:16:10 America/Los_Angeles 94 | - made raw numbers work in import 95 | 96 | 1.20120119 2012-01-19 15:01:10 America/Los_Angeles 97 | - fixed for Perl 5.15.5 and later (ANDK and sprout) 98 | 99 | 1.20120106 2012-01-05 16:26:09 America/Los_Angeles 100 | - loaded IO::File/IO::Handle to allow methods on lexical filehandles 101 | - added unimporting 102 | - removed use of autodie; moved it to a distribution prerequisite 103 | - enabled unicode_strings by default when your Perl supports it 104 | 105 | 1.20120105 2012-01-04 21:01:10 America/Los_Angeles 106 | - migrated to Dist::Zilla 107 | - added autodie dependency/import 108 | 109 | 1.03 Wed Feb 18 00:40:40 UTC 2009 110 | - removed duplicate use lines (Damien Learns Perl) 111 | - fixed (hopefully) v-string warnings (Damien, David Moreno) 112 | - enabled C3 MRO (Evan Carroll) 113 | 114 | 1.02 Tue Jan 27 03:44:29 UTC 2009 115 | - removed the current need for B::Hooks::Parser (suggested by chocolateboy) 116 | 117 | 1.01 Tue Jan 27 01:11:48 UTC 2009 118 | - fixed a documentation typo reported by Vasily Chekalkin 119 | - added caveats to the documentation per bug report from Ben Hengst 120 | 121 | 1.00 Mon Jan 26 22:41:28 UTC 2009 122 | - First version, released on an unsuspecting world. 123 | -------------------------------------------------------------------------------- /lib/Modern/Perl.pm: -------------------------------------------------------------------------------- 1 | package Modern::Perl; 2 | # ABSTRACT: enable all of the features of Modern Perl with one import 3 | 4 | use 5.010_000; 5 | 6 | use strict; 7 | use warnings; 8 | 9 | use mro (); 10 | use feature (); 11 | 12 | # enable methods on filehandles; unnecessary when 5.14 autoloads them 13 | use IO::File (); 14 | use IO::Handle (); 15 | 16 | my $wanted_date; 17 | 18 | sub VERSION { 19 | my ($self, $version) = @_; 20 | 21 | my $default = 2025; 22 | 23 | return $Modern::Perl::VERSION || $default unless defined $version; 24 | return $Modern::Perl::VERSION || $default if $version < 2009; 25 | 26 | $wanted_date = $version if (caller(1))[3] =~ /::BEGIN/; 27 | return $default; 28 | } 29 | 30 | my $unimport_tag; 31 | BEGIN { 32 | $unimport_tag = $] > 5.015 ? ':all' : ':5.10'; 33 | } 34 | 35 | sub import { 36 | my ($class, $date) = @_; 37 | $date = $wanted_date unless defined $date; 38 | 39 | my $feature_tag = validate_date( $date ); 40 | undef $wanted_date; 41 | 42 | warnings->import; 43 | strict->import; 44 | feature->unimport( $unimport_tag ); 45 | feature->import( $feature_tag ); 46 | 47 | if ($feature_tag ge ':5.34') { 48 | feature->import( 'signatures' ); 49 | warnings->unimport( 'experimental::signatures' ); 50 | } 51 | 52 | if ($feature_tag ge ':5.38') { 53 | feature->import( 'module_true' ); 54 | } 55 | 56 | mro::set_mro( scalar caller(), 'c3' ); 57 | } 58 | 59 | sub unimport { 60 | warnings->unimport; 61 | strict->unimport; 62 | feature->unimport; 63 | } 64 | 65 | sub validate_date { 66 | my %dates = ( 67 | 2009 => ':5.10', 68 | 2010 => ':5.10', 69 | 2011 => ':5.12', 70 | 2012 => ':5.14', 71 | 2013 => ':5.16', 72 | 2014 => ':5.18', 73 | 2015 => ':5.20', 74 | 2016 => ':5.24', 75 | 2017 => ':5.24', 76 | 2018 => ':5.26', 77 | 2019 => ':5.28', 78 | 2020 => ':5.30', 79 | 2021 => ':5.32', 80 | 2022 => ':5.34', 81 | 2023 => ':5.36', 82 | 2024 => ':5.38', 83 | 2025 => ':5.40', 84 | ); 85 | 86 | my $date = shift; 87 | 88 | # always enable unicode_strings when available 89 | unless ($date) { 90 | return ':5.12' if $] > 5.011003; 91 | return ':5.10'; 92 | } 93 | 94 | my $year = substr $date, 0, 4; 95 | return $dates{$year} if exists $dates{$year}; 96 | 97 | die "Unknown date '$date' requested\n"; 98 | } 99 | 100 | =encoding utf8 101 | 102 | =head1 SYNOPSIS 103 | 104 | Modern Perl programs use several modules to enable additional features of Perl 105 | and of the CPAN. Instead of copying and pasting all of these C lines, 106 | instead write only one: 107 | 108 | use Modern::Perl; 109 | 110 | This enables the L and L pragmas, as well as all of the 111 | features available in Perl 5.10. It also enables C3 method resolution order as 112 | documented in C and loads L and L so that 113 | you may call methods on filehandles. In the future, it may include additional 114 | core modules and pragmas (but is unlikely to include non-core features). 115 | 116 | Because so much of this module's behavior uses lexically scoped pragmas, you 117 | may disable these pragmas within an inner scope with: 118 | 119 | no Modern::Perl; 120 | 121 | See L for 122 | more information, L for further discussion of 123 | Modern Perl and its implications, and 124 | L for a freely-downloadable 125 | Modern Perl tutorial. 126 | 127 | =head2 CLI Usage 128 | 129 | As of Modern::Perl 2019, you may also enable this pragma from the command line: 130 | 131 | $ perl -Modern::Perl -e 'say "Take that, awk!"' 132 | 133 | You may also enable year-specific features: 134 | 135 | $ perl -Modern::Perl=2020 -e 'say "Looking forward to Perl 5.30!"' 136 | 137 | =head2 Wrapping Modern::Perl 138 | 139 | If you want to wrap Modern::Perl in your own C method, you can do so 140 | to add additional pragmas or features, such as the use of L. Please 141 | note that, if you do so, you will I automatically enable C3 method 142 | resolution in the calling scope. This is due to how the L pragma works. In 143 | your custom C method, you will need to write code such as: 144 | 145 | mro::set_mro( scalar caller(), 'c3' ); 146 | 147 | =head2 Forward Compatibility 148 | 149 | For forward compatibility, I recommend you specify a string containing a 150 | I value as the single optional import tag. For example: 151 | 152 | use Modern::Perl '2009'; 153 | use Modern::Perl '2010'; 154 | 155 | ... both enable 5.10 features, while: 156 | 157 | use Modern::Perl '2011'; 158 | 159 | ... enables 5.12 features: 160 | 161 | use Modern::Perl '2012'; 162 | 163 | ... enables 5.14 features: 164 | 165 | use Modern::Perl '2013'; 166 | 167 | ... enables 5.16 features, and: 168 | 169 | use Modern::Perl '2014'; 170 | 171 | ... enables 5.18 features, and: 172 | 173 | use Modern::Perl '2015'; 174 | 175 | ... enables 5.20 features, and: 176 | 177 | use Modern::Perl '2016'; 178 | 179 | ... enables 5.24 features, and: 180 | 181 | use Modern::Perl '2017'; 182 | 183 | ... enables 5.24 features, and: 184 | 185 | use Modern::Perl '2018'; 186 | 187 | ... enables 5.26 features, and: 188 | 189 | use Modern::Perl '2019'; 190 | 191 | ... enables 5.28 features, and: 192 | 193 | use Modern::Perl '2020'; 194 | 195 | ... enables 5.30 features, and: 196 | 197 | use Modern::Perl '2021'; 198 | 199 | ... enables 5.32 features, and: 200 | 201 | use Modern::Perl '2022'; 202 | 203 | ... enables 5.34 features, and: 204 | 205 | use Modern::Perl '2023'; 206 | 207 | ... enables 5.36 features, and: 208 | 209 | use Modern::Perl '2024'; 210 | 211 | ... enables 5.38 features, and: 212 | 213 | use Modern::Perl '2025'; 214 | 215 | ... enables 5.40 features. 216 | 217 | Obviously you cannot use newer features on earlier versions. Perl will throw 218 | the appropriate exception if you try. 219 | 220 | As of Perl 5.38, you may prefer to write C, which is almost entirely 221 | equivalent to the use of this module. For the purpose of forward compatibility, 222 | this module will continue to work as expected--and will continue regular 223 | maintenance. 224 | 225 | As of Perl 5.41.4, C is no longer available, so any import tags for 226 | older versions of Perl will not enable this feature, no matter how much you try. 227 | 228 | =head1 AUTHOR 229 | 230 | chromatic, C<< >> 231 | 232 | =head1 BUGS 233 | 234 | None known. 235 | 236 | Please report any bugs or feature requests to C, or through the web interface at 238 | L. I will be 239 | notified, and then you'll automatically be notified of progress on your bug as 240 | I make changes. 241 | 242 | =head1 SUPPORT 243 | 244 | You can find documentation for this module with the perldoc command. 245 | 246 | perldoc Modern::Perl 247 | 248 | You can also look for information at: 249 | 250 | =over 4 251 | 252 | =item * RT: CPAN's request tracker 253 | 254 | L 255 | 256 | =item * AnnoCPAN: Annotated CPAN documentation 257 | 258 | L 259 | 260 | =item * CPAN Ratings 261 | 262 | L 263 | 264 | =item * Search CPAN 265 | 266 | L 267 | 268 | =back 269 | 270 | =head1 ACKNOWLEDGEMENTS 271 | 272 | Damian Conway (inspiration from L), Florian Ragwitz 273 | (L, so I didn't have to write it myself), chocolateboy (for 274 | suggesting that I don't even need L), Damien Learns Perl, 275 | David Moreno, Evan Carroll, Elliot Shank, Andreas König, Father Chrysostomos, 276 | Gryphon Shafer, Norbert E. Grüner, and Slaven Rezic for reporting bugs, filing 277 | patches, and requesting features. 278 | 279 | =cut 280 | 281 | 1; 282 | -------------------------------------------------------------------------------- /t/year_imports.t: -------------------------------------------------------------------------------- 1 | #! perl 2 | 3 | use Test::More 0.98; 4 | 5 | use Modern::Perl (); 6 | use Cwd; 7 | use File::Spec; 8 | 9 | if ($ENV{PERL5OPT}) { 10 | plan( skip_all => "Cannot reliably test with PERL5OPT set" ); 11 | exit 0; 12 | } 13 | 14 | $SIG{__WARN__} = sub 15 | { 16 | return if $_[0] =~ /Number found where operator expected/; 17 | return if $_[0] =~ /Do you need to predeclare/; 18 | return if $_[0] =~ /future reserved word/; 19 | return if $_[0] =~ /given is (experimental|deprecated)/; 20 | warn shift 21 | }; 22 | 23 | sub _get_year { 24 | my $year = shift; 25 | return $year eq '()' ? $year : "'$year'"; 26 | } 27 | 28 | sub test_lexical_subs_for 29 | { 30 | # lexical subs removed from feature.pm in 5.25.2 31 | return if $] >= 5.025002; 32 | 33 | my $year = _get_year(shift); 34 | eval qq|use Modern::Perl $year; my sub foo {}|; 35 | isnt $@, '', qq|use Modern::Perl $year should not enable lexical subs|; 36 | } 37 | 38 | sub test_switch_for { 39 | # given removed in 5.41.4 40 | return if $] >= 5.041004; 41 | 42 | my $year = _get_year(shift); 43 | 44 | eval qq|use Modern::Perl $year; sub { given (0) {} }|; 45 | is $@, '', qq|use Modern::Perl $year enables switch|; 46 | } 47 | 48 | sub test_no_switch_for { 49 | # given removed in 5.41.4 50 | return if $] >= 5.041004; 51 | 52 | my $year = _get_year(shift); 53 | 54 | eval qq|use Modern::Perl $year; sub { given (0) {} }|; 55 | isnt $@, '', qq|use Modern::Perl $year does not enable switch|; 56 | } 57 | 58 | sub test_no_indirect_for { 59 | my $year = _get_year(shift); 60 | 61 | my $warning = ''; 62 | local $SIG{__WARN__} = sub { $warning = shift }; 63 | 64 | eval qq|use Modern::Perl $year; my \$foo = new Modern::Perl;|; 65 | like $@, qr/syntax error.+near "new Modern::Perl"/, 66 | qq|use Modern::Perl $year disables indirect method calls|; 67 | } 68 | 69 | sub test_no_multidimensional_for { 70 | my $year = _get_year(shift); 71 | 72 | my $warning = ''; 73 | local $SIG{__WARN__} = sub { $warning = shift }; 74 | 75 | eval qq{ 76 | use Modern::Perl $year; 77 | my (\$x, \$y) = (1, 2); 78 | my %foo; 79 | 80 | \$foo{\$x, \$y} = 'bar'; 81 | }; 82 | like $@, qr/Multidimensional hash lookup is disabled/, 83 | qq|use Modern::Perl $year disables multidimensional array emulation|; 84 | } 85 | 86 | sub test_say_for { 87 | my $year = _get_year(shift); 88 | 89 | eval qq|use Modern::Perl $year; sub { say 0 }|; 90 | is $@, '', qq|use Modern::Perl $year enables say|; 91 | } 92 | 93 | sub test_state_for { 94 | my $year = _get_year(shift); 95 | 96 | eval qq|use Modern::Perl $year; state \$x;|; 97 | is $@, '', qq|use Modern::Perl $year enables state|; 98 | } 99 | 100 | sub test_cur_sub_for { 101 | my $year = _get_year(shift); 102 | 103 | eval qq|use Modern::Perl $year; sub { return __SUB__ }|; 104 | is $@, '', qq|use Modern::Perl $year enables current_sub|; 105 | } 106 | 107 | sub test_array_base_for { 108 | my $year = _get_year(shift); 109 | 110 | my $warning = ''; 111 | local $SIG{__WARN__} = sub { $warning = shift }; 112 | 113 | if (eval qq|use Modern::Perl $year; \$[ = 10|) { 114 | like $warning, qr/Use of assignment to \$\[ is deprecated/, 115 | qq|use Modern::Perl $year disables array_base|; 116 | } 117 | else { 118 | like $@, qr/Assigning non-zero to \$\[ is no longer possible/, 119 | qq|use Modern::Perl $year works without array_base|; 120 | } 121 | } 122 | 123 | sub test_fc_for { 124 | my $year = _get_year(shift); 125 | 126 | eval qq|use Modern::Perl $year; fc("tschüß") eq fc("TSCHÜSS")|; 127 | is $@, '', qq|use Modern::Perl $year enables fc|; 128 | } 129 | 130 | sub test_postderef_for { 131 | my $year = _get_year(shift); 132 | 133 | eval qq|use Modern::Perl $year; my \$r = [ 1, [ 2, 3 ], 4 ]; \$r->[1]->@*|; 134 | is $@, '', qq|use Modern::Perl $year enables postderef_qq|; 135 | } 136 | 137 | sub test_unicode_strings_for { 138 | my $year = _get_year(shift); 139 | 140 | eval qq{ 141 | use Modern::Perl $year; 142 | is uc "\xdf", "SS", q|use Modern::Perl $year enables unicode_strings|; 143 | }; 144 | } 145 | 146 | sub test_signatures_for { 147 | my $year = _get_year(shift); 148 | 149 | my @warnings; 150 | local $SIG{__WARN__} = sub { push @warnings, @_ }; 151 | 152 | local $@; 153 | my ($yearnum) = $year =~ m/(\d+)/; 154 | eval qq{ 155 | use Modern::Perl $year; 156 | sub foo_$yearnum( \$bar ) { ... } 157 | }; 158 | is $@, '', qq|use Modern::Perl $year enables signatures|; 159 | is @warnings, 0, '... and disables signature warnings'; 160 | } 161 | 162 | sub test_isa_for { 163 | my $year = _get_year(shift); 164 | 165 | eval qq{ 166 | use Modern::Perl $year; 167 | my \$foo = bless {}, 'Some::Class'; 168 | my \$result = \$foo isa 'Some::Class'; 169 | }; 170 | is $@, '', qq|use Modern::Perl $year enables isa|; 171 | } 172 | 173 | sub test_warnings_for { 174 | my $year = _get_year(shift); 175 | 176 | my $warnings; 177 | 178 | local $SIG{__WARN__} = sub { $warnings = shift }; 179 | 180 | eval qq{ 181 | no warnings; 182 | use Modern::Perl $year; 183 | my \$x = "2:" + 3; 184 | }; 185 | 186 | like $warnings, qr/Argument "2:" isn't numeric/, qq|use Modern::Perl $year enables warnings|; 187 | } 188 | 189 | sub test_module_true_for { 190 | my $year = _get_year(shift); 191 | my $cwd = Cwd::cwd(); 192 | my $tmpdir = File::Spec->tmpdir; 193 | 194 | chdir $tmpdir; 195 | 196 | open my $fh, '>', 'Foo.pm' 197 | or die "Cannot write 'Foo.pm': $!\n"; 198 | 199 | # don't use <<~ heredoc to trim whitespace 200 | # as this will fail with Perl < 5.26 201 | # see RT #151189 202 | $fh->print(<bar; 219 | }; 220 | 221 | is $result, 'returned from Foo::bar()', 222 | qq|use Modern::Perl $year enables module_true|; 223 | 224 | chdir $cwd; 225 | } 226 | 227 | eval 'sub { given (0) {} }'; 228 | isnt $@, '', 'use Modern::Perl () does not enable switch'; 229 | 230 | eval 'sub { say 0 }'; 231 | isnt $@, '', 'use Modern::Perl () does not enable say'; 232 | 233 | eval 'state $x;'; 234 | isnt $@, '', 'use Modern::Perl () does not enable state'; 235 | is uc "\xdf", "\xdf", 'Modern::Perl () does not enable unicode_strings'; 236 | 237 | eval 'sub { return __SUB__ }'; 238 | is $@, '', q|use Modern::Perl '2013' does not enable current_sub|; 239 | 240 | { 241 | my $warning = ''; 242 | local $SIG{__WARN__} = sub { $warning = shift }; 243 | eval 'fc("tschüß") eq fc("TSCHÜSS")'; 244 | isnt $@, '', q|use Modern::Perl () does not enable fc|; 245 | } 246 | 247 | { 248 | use Modern::Perl '2009'; 249 | 250 | test_switch_for( '2009' ); 251 | test_say_for( '2009' ); 252 | test_state_for( '2009' ); 253 | 254 | is uc "\xdf", "\xdf", q|use Modern::Perl '2009' does not enable unicode_strings|; 255 | } 256 | 257 | { 258 | use Modern::Perl '2010'; 259 | 260 | test_switch_for( '2010' ); 261 | test_say_for( '2010' ); 262 | test_state_for( '2010' ); 263 | 264 | is uc "\xdf", "\xdf", q|use Modern::Perl '2010' does not enable unicode_strings|; 265 | } 266 | 267 | if ($] >= 5.012) 268 | { 269 | my $year = 2011; 270 | 271 | test_switch_for( $year ); 272 | test_say_for( $year ); 273 | test_state_for( $year ); 274 | test_unicode_strings_for( $year ); 275 | } 276 | 277 | if ($] >= 5.014) 278 | { 279 | my $year = 2012; 280 | 281 | test_switch_for( $year ); 282 | test_say_for( $year ); 283 | test_state_for( $year ); 284 | test_unicode_strings_for( $year ); 285 | } 286 | 287 | if ($] >= 5.016) 288 | { 289 | my $year = 2013; 290 | 291 | test_switch_for( $year ); 292 | test_say_for( $year ); 293 | test_state_for( $year ); 294 | test_cur_sub_for( $year ); 295 | test_array_base_for( $year ); 296 | test_lexical_subs_for( $year ); 297 | test_fc_for( $year ); 298 | test_unicode_strings_for( $year ); 299 | } 300 | 301 | if ($] >= 5.018) 302 | { 303 | my $year = 2014; 304 | 305 | test_switch_for( $year ); 306 | test_say_for( $year ); 307 | test_state_for( $year ); 308 | test_cur_sub_for( $year ); 309 | test_array_base_for( $year ); 310 | test_lexical_subs_for( $year ); 311 | test_fc_for( $year ); 312 | test_unicode_strings_for( $year ); 313 | } 314 | 315 | if ($] >= 5.020) 316 | { 317 | my $year = 2015; 318 | 319 | test_switch_for( $year ); 320 | test_say_for( $year ); 321 | test_state_for( $year ); 322 | test_cur_sub_for( $year ); 323 | test_array_base_for( $year ); 324 | test_lexical_subs_for( $year ); 325 | test_fc_for( $year ); 326 | test_unicode_strings_for( $year ); 327 | } 328 | 329 | if ($] >= 5.024) 330 | { 331 | my $year = 2016; 332 | 333 | test_switch_for( $year ); 334 | test_say_for( $year ); 335 | test_state_for( $year ); 336 | test_cur_sub_for( $year ); 337 | test_array_base_for( $year ); 338 | test_lexical_subs_for( $year ); 339 | test_fc_for( $year ); 340 | test_postderef_for( $year ); 341 | test_unicode_strings_for( $year ); 342 | } 343 | 344 | if ($] >= 5.024) 345 | { 346 | my $year = 2017; 347 | 348 | test_switch_for( $year ); 349 | test_say_for( $year ); 350 | test_state_for( $year ); 351 | test_cur_sub_for( $year ); 352 | test_array_base_for( $year ); 353 | test_lexical_subs_for( $year ); 354 | test_fc_for( $year ); 355 | test_postderef_for( $year ); 356 | test_unicode_strings_for( $year ); 357 | } 358 | 359 | if ($] >= 5.026) 360 | { 361 | my $year = 2018; 362 | 363 | test_switch_for( $year ); 364 | test_say_for( $year ); 365 | test_state_for( $year ); 366 | test_cur_sub_for( $year ); 367 | test_array_base_for( $year ); 368 | test_lexical_subs_for( $year ); 369 | test_fc_for( $year ); 370 | test_postderef_for( $year ); 371 | test_unicode_strings_for( $year ); 372 | } 373 | 374 | if ($] >= 5.028) 375 | { 376 | my $year = 2019; 377 | 378 | test_switch_for( $year ); 379 | test_say_for( $year ); 380 | test_state_for( $year ); 381 | test_cur_sub_for( $year ); 382 | test_array_base_for( $year ); 383 | test_lexical_subs_for( $year ); 384 | test_fc_for( $year ); 385 | test_postderef_for( $year ); 386 | test_unicode_strings_for( $year ); 387 | } 388 | 389 | if ($] >= 5.030) 390 | { 391 | my $year = 2020; 392 | 393 | test_switch_for( $year ); 394 | test_say_for( $year ); 395 | test_state_for( $year ); 396 | test_cur_sub_for( $year ); 397 | test_array_base_for( $year ); 398 | test_lexical_subs_for( $year ); 399 | test_fc_for( $year ); 400 | test_postderef_for( $year ); 401 | test_unicode_strings_for( $year ); 402 | } 403 | 404 | if ($] >= 5.032) 405 | { 406 | my $year = 2021; 407 | 408 | test_switch_for( $year ); 409 | test_say_for( $year ); 410 | test_state_for( $year ); 411 | test_cur_sub_for( $year ); 412 | test_array_base_for( $year ); 413 | test_lexical_subs_for( $year ); 414 | test_fc_for( $year ); 415 | test_postderef_for( $year ); 416 | test_unicode_strings_for( $year ); 417 | } 418 | 419 | if ($] >= 5.034) 420 | { 421 | my $year = 2022; 422 | 423 | test_switch_for( $year ); 424 | test_say_for( $year ); 425 | test_state_for( $year ); 426 | test_cur_sub_for( $year ); 427 | test_array_base_for( $year ); 428 | test_lexical_subs_for( $year ); 429 | test_fc_for( $year ); 430 | test_postderef_for( $year ); 431 | test_unicode_strings_for( $year ); 432 | test_signatures_for( $year ); 433 | } 434 | 435 | if ($] >= 5.036) 436 | { 437 | my $year = 2023; 438 | 439 | test_no_switch_for( $year ); 440 | test_no_indirect_for( $year ); 441 | test_no_multidimensional_for( $year ); 442 | 443 | test_say_for( $year ); 444 | test_state_for( $year ); 445 | test_cur_sub_for( $year ); 446 | test_array_base_for( $year ); 447 | test_lexical_subs_for( $year ); 448 | test_fc_for( $year ); 449 | test_postderef_for( $year ); 450 | test_unicode_strings_for( $year ); 451 | test_signatures_for( $year ); 452 | test_isa_for( $year ); 453 | test_warnings_for( $year ); 454 | } 455 | 456 | if ($] >= 5.038) 457 | { 458 | my $year = 2024; 459 | 460 | test_no_switch_for( $year ); 461 | test_no_indirect_for( $year ); 462 | test_no_multidimensional_for( $year ); 463 | 464 | test_say_for( $year ); 465 | test_state_for( $year ); 466 | test_cur_sub_for( $year ); 467 | test_array_base_for( $year ); 468 | test_lexical_subs_for( $year ); 469 | test_fc_for( $year ); 470 | test_postderef_for( $year ); 471 | test_unicode_strings_for( $year ); 472 | test_signatures_for( $year ); 473 | test_isa_for( $year ); 474 | test_warnings_for( $year ); 475 | test_module_true_for( $year ); 476 | } 477 | 478 | if ($] >= 5.040) 479 | { 480 | my $year = 2025; 481 | 482 | test_no_switch_for( $year ); 483 | test_no_indirect_for( $year ); 484 | test_no_multidimensional_for( $year ); 485 | 486 | test_say_for( $year ); 487 | test_state_for( $year ); 488 | test_cur_sub_for( $year ); 489 | test_array_base_for( $year ); 490 | test_lexical_subs_for( $year ); 491 | test_fc_for( $year ); 492 | test_postderef_for( $year ); 493 | test_unicode_strings_for( $year ); 494 | test_signatures_for( $year ); 495 | test_isa_for( $year ); 496 | test_warnings_for( $year ); 497 | test_module_true_for( $year ); 498 | } 499 | 500 | eval 'sub { given (0) {} }'; 501 | isnt $@, "", 'switch feature does not leak out'; 502 | eval 'sub { say 0 }'; 503 | isnt $@, '', 'say feature does not leak out'; 504 | eval 'state $x'; 505 | isnt $@, '', 'state feature does not leak out'; 506 | is uc "\xdf", "\xdf", 'unicode_strings feature does not leak out'; 507 | 508 | done_testing; 509 | --------------------------------------------------------------------------------