Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I slice a string like Python does in Perl 6?

In Python, I can splice string like this:

solo = A quick brown fox jump over the lazy dog
solo[3:5]

I know substr and comb is enough, I want to know if it's possible, However. Should I use a role to do this?

like image 908
ohmycloudy Avatar asked Dec 07 '22 19:12

ohmycloudy


1 Answers

How to slice a string

Strings (represented as class Str) are seen as single values and not positional data structures in Perl 6, and thus can't be indexed/sliced with the built-in [ ] array indexing operator.

As you already suggested, comb or substr is the way to go:

my $solo = "A quick brown fox jumps over the lazy dog";

dd $solo.comb[3..4].join;   # "ui"
dd $solo.comb[3..^5].join;  # "ui"

dd $solo.substr(3, 2);      # "ui"
dd $solo.substr(3..4);      # "ui"
dd $solo.substr(3..^5);     # "ui"

If you want to modify the slice, use substr-rw:

$solo.substr-rw(2..6) = "slow";
dd $solo;  # "A slow brown fox jumps over the lazy dog"

How to make operator [ ] work directly on strings

If you really wanted to, you could compose a role into your string that adds method AT-POS, which would make the [ ] operator work on it:

my $solo = "A quick brown fox jumps over the lazy dog" but role {
    method AT-POS ($i) { self.substr($i, 1) }
}

dd $solo[3..5]; ("u", "i", "c")

However, this returns slices as a list, because that's what the [ ] operator does by default. To make it return a concatenated string, you'd have to re-implement [ ] for type Str:

multi postcircumfix:<[ ]>(Str $string, Int:D $index) {
    $string.substr($index, 1)
}
multi postcircumfix:<[ ]>(Str $string, Range:D $slice) {
    $string.substr($slice)
}
multi postcircumfix:<[ ]>(Str $string, Iterable:D \slice) {
    slice.map({ $string.substr($_, 1) }).join
}

my $solo = "A quick brown fox jumps over the lazy dog";

dd $solo[3];     # "u"
dd $solo[3..4];  # "ui"
dd $solo[3, 5];  # "uc"

You could extend the [ ] multi-candidates added here to handle all the other magic that the operator provides for lists, like:

  • from-the-end indices, e.g. $solo[*-1]
  • truncating slices, e.g. $solo[3..*]
  • adverbs, e.g. $solo[3..5]:kv
  • assignment, e.g. $solo[2..6] = "slow"

But it would take a lot of effort to get all of that right.

Also, keep in mind that overriding built-in operators to do things they weren't supposed to do, will confuse other Perl 6 programmers who will have to review or work with your code in the future.

like image 79
smls Avatar answered Jan 20 '23 13:01

smls