I'm trying to apply a text substitution to an entire array.
However, when I try to alter the array, it shows that it only has 1 element, when it should have 26.
An example below in Perl6 REPL:
> my @a = 'a'..'z'
[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]
> my @a1 = @a.subst(/<[aeiou]>/, 1, :g)
[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]
> @a1.elems
1#this should be 26
> @a.elems
26
how can I alter an array with a text substitution across the entire array, and return an array?
also: the perl6 website is down, I can't access the many manual pages :(
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With