package feature; our $VERSION = '1.10'; # (feature name) => (internal name, used in %^H) my %feature = ( switch => 'feature_switch', say => "feature_say", err => "feature_err", state => "feature_state", ); my %feature_bundle = ( "5.10.0" => [qw(switch say err state)], ); # latest version here # keep it harcoded until we actually bump the version number to 5.10 $feature_bundle{"5.10"} = $feature_bundle{"5.10.0"}; #$feature_bundle{"5.10"} = $feature_bundle{sprintf("%vd",$^V)}; $feature_bundle{"5.9.5"} = $feature_bundle{"5.10.0"}; # TODO: # - think about versioned features (use feature switch => 2) =head1 NAME feature - Perl pragma to enable new syntactic features =head1 SYNOPSIS use feature qw(switch say); given ($foo) { when (1) { say "\$foo == 1" } when ([2,3]) { say "\$foo == 2 || \$foo == 3" } when (/^a[bc]d$/) { say "\$foo eq 'abd' || \$foo eq 'acd'" } when ($_ > 100) { say "\$foo > 100" } default { say "None of the above" } } use feature ':5.10'; # loads all features available in perl 5.10 =head1 DESCRIPTION It is usually impossible to add new syntax to Perl without breaking some existing programs. This pragma provides a way to minimize that risk. New syntactic constructs can be enabled by C, and will be parsed only when the appropriate feature pragma is in scope. =head2 Lexical effect Like other pragmas (C, for example), features have a lexical effect. C will only make the feature "foo" available from that point to the end of the enclosing block. { use feature 'say'; say "say is available here"; } print "But not here.\n"; =head2 C Features can also be turned off by using C. This too has lexical effect. use feature 'say'; say "say is available here"; { no feature 'say'; print "But not here.\n"; } say "Yet it is here."; C with no features specified will turn off all features. =head2 The 'switch' feature C tells the compiler to enable the Perl 6 given/when construct. See L for details. =head2 The 'say' feature C tells the compiler to enable the Perl 6 C function. See L for details. =head2 the 'err' feature C tells the compiler to enable the C operator. C is a low-precedence variant of the C operator: see C for details. =head2 the 'state' feature C tells the compiler to enable C variables. See L for details. =head1 FEATURE BUNDLES It's possible to load a whole slew of features in one go, using a I. The name of a feature bundle is prefixed with a colon, to distinguish it from an actual feature. At present, the only feature bundles are C and C, which both are equivalent to C. In the forthcoming 5.10.X perl releases, C will be equivalent to the latest C. =head1 IMPLICIT LOADING There are two ways to load the C pragma implicitly : =over 4 =item * By using the C<-E> switch on the command-line instead of C<-e>. It enables all available features in the main compilation unit (that is, the one-liner.) =item * By requiring explicitly a minimal Perl version number for your program, with the C construct, and when the version is higher than or equal to 5.9.5. That is, use 5.9.5; will do an implicit use feature ':5.9.5'; and so on. =back =cut sub import { my $class = shift; if (@_ == 0) { croak("No features specified"); } while (@_) { my $name = shift(@_); if ($name =~ /^:(.*)/) { if (!exists $feature_bundle{$1}) { unknown_feature_bundle($1); } unshift @_, @{$feature_bundle{$1}}; next; } if (!exists $feature{$name}) { unknown_feature($name); } $^H{$feature{$name}} = 1; } } sub unimport { my $class = shift; # A bare C should disable *all* features if (!@_) { delete @^H{ values(%feature) }; return; } while (@_) { my $name = shift; if ($name =~ /^:(.*)/) { if (!exists $feature_bundle{$1}) { unknown_feature_bundle($1); } unshift @_, @{$feature_bundle{$1}}; next; } if (!exists($feature{$name})) { unknown_feature($name); } else { delete $^H{$feature{$name}}; } } } sub unknown_feature { my $feature = shift; croak(sprintf('Feature "%s" is not supported by Perl %vd', $feature, $^V)); } sub unknown_feature_bundle { my $feature = shift; croak(sprintf('Feature bundle "%s" is not supported by Perl %vd', $feature, $^V)); } sub croak { require Carp; Carp::croak(@_); } 1;