New Features of Perl 5.14: Non-destructive Substitution

Perl 5.14 is now available. While this latest major release of Perl 5 brings with it many bugfixes, updates to the core libraries, and the usual performance improvements, it also includes a few nice new features.

One such feature is non-destructive substitution:

    use 5.014;

    my $greeting  = 'Hello, world!';

    # be more elite
    say $greeting =~ tr/aeiou/4310V/r;

    # then run away
    say $greeting =~ s/Hello/Goodbye/r;

The new /r modifier to the substitution and transliteration operators causes Perl to return the modified string, rather than modifying the original string in place. This replaces the idiomatic but unwieldy:

    my  $greeting  = 'Hello, world!';
    my ($leetgreet = $greeting) =~ tr/aeiou/4310V/;

This feature is even more useful for avoiding two common problems with substitutions in map expressions:

    my @modified = map { s/foo/BAR/ } @original;

Not only does the substitution modify the values of @original in place, but the substitution returns a true value if the substitution succeeded and a false value otherwise. While that code looks correct, it’s very subtly wrong. The corrected version of this code in Perl 5.12 or earlier is:

    my @modified = map { my $copy = $_; $copy =~ s/foo/BAR/; $copy } @original;

5.14 requires the addition of a single character to produce the intended behavior:

    my @modified = map { s/foo/BAR/r } @original;

See perldoc perlop for documentation of the /r modifier.



Something wrong with this article? Help us out by opening an issue or pull request on GitHub