perl6 text substitution on array

By using the >>. hyper operator: this calls the given method on each element of the list, and creates a list of the result of the call.

my @a = "a".."z";
my @b = @a>>.subst(/ <[aeiou]> /, 1, :g);
dd @a, @b;

# Array @a = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
# Array @b = ["1", "b", "c", "d", "1", "f", "g", "h", "1", "j", "k", "l", "m", "n", "1", "p", "q", "r", "s", "t", "1", "v", "w", "x", "y", "z"]

.subst is a Str method.

What that means is that it assumes it's first argument (the invocant) is a Str. If it isn't already a Str it gets coerced into a Str.

When you call .Str on an array, it joins all of the values together with a space as a separator.

my @a = < a b c >;
say @a.perl;       # ["a", "b", "c"]
say @a.Str.perl;   # "a b c"

So these three lines are exactly equivalent:

@a.subst(/<[aeiou]>/, 1, :g);
@a.Str.subst(/<[aeiou]>/, 1, :g);
@a.join(" ").subst(/<[aeiou]>/, 1, :g);

Perl6 does this because it is consistent. You always know that the output of a single call to .subst is a single Str. You also know that the invocant is treated as a Str.

If it did something different on arrays, it would become difficult to keep track of which methods change depending on there invocant and how they change.

We have only to look at Perl5 to see how hard it is to remember every quirk of every function when they aren't consistent.
(Try to think of all of the functions in Perl5 which operate on $_ by default, and what they do in scalar vs. list context.)


Instead of calling .subst on the single array value, you want to call it on each of the values it contains.

There are several ways to do that:

my @ = @a.map( *.subst(…) )

my @ = @a».subst(…)

my @ = do for @a { .subst(…) }

my @ = @a.duckmap( -> Str $_ { .subst(…) } ) # only change Str's

Tags:

Raku