Perl Features
A few pages about features introduced in certain version of Perl.
Some of these features have changed or were removed since then.
Advanced Features in 5.10
Advanced Features
When there is an uninitialized value, 5.10 will include the name of the variable in the warning.
defined or
- //
- defined-or
How do you set a default value of a scalar?
$x = defined $x ? $x : $DEFAULT;
$x ||= $DEFAULT;
$x //= $DEFAULT;
#!/usr/bin/perl
use strict;
use warnings;
my $val;
print defined $val ? "defined\n" : "not defined\n"; # not defined
$val //= 42;
print "$val\n"; # 42
$val = 0;
print "$val\n"; # 0
$val //= 42;
print "$val\n"; # 0
Turn on features explicitly
- feature
- v5.10
use feature qw(say);
use feature qw(:5.10);
use 5.010;
use v5.10;
say
- say
#!/usr/bin/perl
use strict;
use warnings;
use feature qw(say);
my $hello = "Hello world";
say $hello;
feature is a lexical pragma
{
use feature qw(say);
say $var;
}
print "Cannot use say here\n";
static variable (with scope)
- static
#!/usr/bin/perl
use strict;
use warnings;
{
my $counter = 0;
sub next_counter {
$counter++;
return $counter;
}
}
print next_counter(), "\n";
print next_counter(), "\n";
state variable
- state
- static
In Perl 5.10 the state keyword was added that allows us to create a static variable. When we declare such variable in a function the declaration and the initialization
takes places only once no matter how many times the function is called. Instead of being initialized every time we enter the function like a variable declared with my
would
do, state
variables are initialized only once and then they remember their value for the subsequent calls to the same function.
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
sub next_counter {
state $counter = 0;
$counter++;
return $counter;
}
say next_counter();
say next_counter();
say next_counter();
1
2
3
regex: Named capture buffers
- %+
- %-
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my @data = (
"line 100 long ",
"we have a number 42 here ",
);
foreach my $line (@data) {
if ($line =~ m/(\d+)/) {
print "number: $1\n";
}
if ($line =~ m/(?<number>\d+)/) {
print "number: $+{number}\n";
}
if ($line =~ m/((?<str>\w+)\s+)*/) {
print "str: $+{str}\n";
print "str all: @{$-{str}}\n";
print "all: $&\n";
}
if ($line =~ m/(?<str>\w+)\s+(?<str>\w+)/) {
print "2 str: $+{str}\n";
print "2 str all: " . join(",", @{$-{str}}) . "\n";
print "2 all: $&\n";
}
if ($line =~ m/(?<str>\w+) .* \k<str> /x) {
print "Matched $+{str} in '$&'\n";
}
}
__END__
my @data = (
"engine = Thomas",
);
foreach my $line (@data) {
if ($line =~ m/(\w+)\s*=\s*(\w+)/) {
print "Field=$1, value=$2\n";
}
if ($line =~ m/(?<field>\w+)\s*=\s*(?'value'\w+)/) {
print "Field=$+{field}, value=$+{value}\n";
}
}
See also the values in these two hashes:
%+ hash contains the left most match with the given name
%+{name}
%- hash contains and array of the matches
%-{name}[0]
Possessive quantifier
- ++
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
say ("aaa" =~ / a+ a /x ? 'YES' : 'NO'); # matched
say ("aaa" =~ / a++ a /x ? 'YES' : 'NO'); # does NOT match
Mainly for speed improvements
smartmatch ~~ - Don't use it!
~~ compares values as strings
unless there is a better way to compare them
So it can do things like
"Foo" ~~ "Foo"
42 ~~ 42
42 ~~ 42.0
42 ~~ "42.0"
42 ~~ "23"
And even
$name ~~ @people
@people ~~ $name
$name ~~ %phonebook
$name ~~ qr/regex-perl/
~~ decides how to compare based on the values
perldoc perlsyn
Smart matching in detail
$a $b Type of Match Implied Matching Code
====== ===== ===================== =============
(overloading trumps everything)
Code[+] Code[+] referential equality $a == $b
Any Code[+] scalar sub truth $b->($a)
Hash Hash hash keys identical [sort keys %$a]~~[sort keys %$b]
Hash Array hash slice existence grep {exists $a->{$_}} @$b
Hash Regex hash key grep grep /$b/, keys %$a
Hash Any hash entry existence exists $a->{$b}
Array Array arrays are identical[*]
Array Regex array grep grep /$b/, @$a
Array Num array contains number grep $_ == $b, @$a
Array Any array contains string grep $_ eq $b, @$a
Any undef undefined !defined $a
Any Regex pattern match $a =~ /$b/
Code() Code() results are equal $a->() eq $b->()
Any Code() simple closure truth $b->() # ignoring $a
Num numish[!] numeric equality $a == $b
Any Str string equality $a eq $b
Any Num numeric equality $a == $b
Any Any string equality $a eq $b
Smart match example - Don't use it!
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
sub compare {
my ($x, $y, $d) = @_;
my $t = ($x ~~ $y ? "True" : "False");
$x //= '';
$y //= '';
printf("%-4s ~~ %-4s is %-5s (%s)\n", $x, $y, $t, $d);
}
compare("Foo", "Foo", "Any ~~ Any => eq");
compare("Foo", "Bar", "Any ~~ Any => eq");
compare(42, 42, "Any ~~ Num => ==");
compare(42, 42.0, "Any ~~ Num => ==");
compare(42, "42x", "Any ~~ Str => eq");
compare(42, "42", "Any ~~ numish => ==");
compare(42, "42.0", "Any ~~ numish => ==");
#compare(42, "42\n", "Any ~~ numish => ==");
compare(42, "42 ", "Any ~~ numish => ==");
compare("42", "42.0", "numish ~~ numish => eq");
compare(42, undef, "Any ~~ undef => defined ?");
compare(undef, undef, "Any ~~ undef => defined ?");
compare("Moose", [qw(Foo Bar Baz)], "Str ~~ Array");
compare("Moose", [qw(Foo Bar Moose Baz)], "Str ~~ Array");
# And of course if the individual value is a number then
# each individual element of the array is checked using ==
compare(42, [23, 17, 70], "Num ~~ Array");
compare(42, [23, 17, 42, 70], "Num ~~ Array");
compare(42, [23, 17, "42\n", 70], "Num ~~ Array");
compare(42, [23, 17, "42 ", 70], "Num ~~ Array");
#compare(42, [23, 17, "42x", 70], "Num ~~ Array");
# this generates a warning when trying to == "42x"
# If there can be an array reference then we can also have a HASH reference there
# The smart match will check if the given scalar is one of the keys in the hash
# That is using exists
compare('a', {a => 19, b => 23}, "Str ~~ HASH");
compare(42, {a => 19, b => 23}, "Num ~~ HASH");
# The obvious question then what happens when both sides are
# complex data structures (Arrays or Hashes?)
# With Arrays, it check if each element is the same
compare(["Foo", "Bar"], ["Foo", "Bar"], "Array ~~ Array");
compare(["Foo", "Bar"], ["Foo", "Bar", "Baz"], "Array ~~ Array");
compare([1,2,3], [1,2,3], "Array ~~ Array");
compare({Foo => 19, Bar => 23}, {Foo => 23, Bar => 19}, "Hash ~~ Hash");
compare(["Foo", ["Bar", "Baz"]],
["Foo", ["Bar", "Baz"]],
"Complex Array ~~ Complex Array");
compare("Perl 5.10", qr/Moose/, "Str ~~ Regex");
compare(qr/Moose/, "Perl 5.10", "Regex ~~ Str");
compare("Perl 5.10", qr/Perl/, "Str ~~ Regex");
compare(qr/Perl/, "Perl 5.10", "Regex ~~ Str");
say /Perl/ ~~ "Perl 5.10" ? "T" : "F";
# Side note, instead of reference to Array or reference to Hash
# you can actually put there
# the real Array or the real Hash (but not a simle list) so
# this works:
my @a = (2, 3);
say 3 ~~ @a ? "T" : "F";
# but this does not:
#say 3 ~~ (2, 3) ? "T" : "F";
#my @m = ([ 2, 3], [4, 5]);
#say 3 ~~ @m ? "T" : "F";
say 1 ~~ \&true ? "T" : "F";
say 0 ~~ \&true ? "T" : "F";
# There are more complex cases as well but let's get back now to the scalars
# We can have other values in scalars as well, eg, regular expressions and
sub true {
return $_[0];
}
__END__
{
my $x = 42;
my $y = "42";
say "Compare $x and $y";
if ($x == $y) {
say "== Same numbers";
}
if ($x ~~ $y) {
say "~~ Same numbers";
}
}
{
my $x = 42;
my $y = "42.0";
say "Compare $x and $y";
if ($x == $y) {
say "== Same numbers";
}
if ($x ne $y) {
say "ne Different strings";
}
if ($x ~~ $y) {
say "~~ Same numbers";
}
}
{
my $x = 42;
my $y = "42x";
say "Compare $x and $y";
# if ($x == $y) {
# say "== Same numbers";
# }
if ($x ne $y) {
say "ne Different strings";
}
if ($x ~~ $y) {
say "~~ Same numbers";
}
}
switch - Don't use it!
- switch
- case
- given
- when
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
my $value = <STDIN>;
chomp $value;
given($value) {
when(3) { say "Three"; }
when(7) { say "Seven"; }
when(9) { say "Nine"; }
default { say "Non of the expected values"; }
}
given($value) {
when(/^\d+$/) { say "digits only"; }
when(/^\w+$/) { say "Word characters"; }
when(/^[a-zA-Z0-9.-]+$/) { say "Domain namish"; }
default { say "Non of the expected"; }
}
given($value) {
when(10) {
say "Number 10";
}
when([11, 23, 48]) {
say "In the list";
}
when($_ < 21) {
say "under 21";
}
when(/^\d+$/) {
say "digits only";
}
when(\&is_number) {
say "Is number";
}
default {
say "None of the above";
}
}
sub is_number {
return $_[0] =~ /\d/ and $_[0] =~ /^[+-]?\d*\.\d*$/;
}
New features in 5.12
Perl 5.12 features
- Y2038 compliance
- Pluggable Keywords
- configure_requires in CPAN module meta data (META.yml)
- deprecations warn by default
Implicit stricture
- v5.12
no need to write use strict any more
use v5.12;
$x = 23;
say $x;
Global symbol "$x" requires explicit package name at a.pl line 3.
Global symbol "$x" requires explicit package name at a.pl line 4.
Execution of a.pl aborted due to compilation errors.
use parent
- parent
use parent qw(Foo Bar);
use parent instead of base
package NAME VERSION
- package Foo v5.12
package Foo 1.00;
Yada Yada Operator...
- ...
- Yada Yada
sub new {
...
}
Unimplemented at Foo.pm line 5.
each on arrays
- each
while (my ($index, $value) = each @a) {
say "$index $value";
}
0 a
1 b
2 c
delete local
- delete local
my %h = (foo => 'bar');
say exists $h{foo} ? 1 : 0;
{
delete local $h{foo};
say exists $h{foo} ? 1 : 0;
}
say exists $h{foo} ? 1 : 0;
1
0
1