Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl6 text substitution on array

Tags:

raku

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 :(

like image 310
con Avatar asked Apr 23 '19 17:04

con


2 Answers

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"]
like image 172
Elizabeth Mattijsen Avatar answered Nov 14 '22 23:11

Elizabeth Mattijsen


.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
like image 45
Brad Gilbert Avatar answered Nov 15 '22 01:11

Brad Gilbert