6

How is the simplest Raku to fill out so many individual variables from a result regex captures in corresponding order
( just like Perl my ($a, $b $c, $d, $e)= 'hello' =~ m{ ^(h) (e) (l) (l) (o) }x

) ?

try such:

> my ($a, $b, $c, $arr);
[<$a $b $c>]= 'hello world' ~~ m{ (h)(e)(l)lo };
say "\n=$a\n=$b\n=$c"

Use of uninitialized value element of type Any in string context.
    Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful.
      in block <unit> at <unknown file> line 1

...

fails.
Please show the correct and nearest similar way to Perl.

itil memek cantik
  • 1,167
  • 2
  • 11

2 Answers2

7
#my ($a, $b, $c, $d, $e) = 'hello' =~ m{ ^(h) (e) (l) (l) (o) }x;      # Perl
 my ($a, $b, $c, $d, $e) = 'hello' ~~ m{ ^(h) (e) (l) (l) (o) } .list; # Raku

Explaining the differences:

  • { ... }x In Perl, white space in a regex is part of the pattern unless you append an x adverb/option. Not so in Raku.

  • .list. In Perl, matching operations generally return either one string, or a list of strings. It's the same in Raku, except:

    • The values returned are Match objects, not strings. (They conveniently automatically coerce to strings if treated as strings, but the difference sometimes matters, and greatly expands what Raku can make possible/easy with the returned matches.)

    • Many operations return a single Match object when Perl folk will expect a list. Your case is an example. But what exactly is a single object? You are a single person. But you're also more than that.

    • Some objects in Raku are a "parent" of "child" objects. (Match objects are a case in point.) Children are typically accessible by applying appropriate operations to a parent. Your case is an example. .list will often work as an idiomatic way to get at numbered children, .hash for named children. Another approach among many that will work if a given class/object supports it is subscripting:

      say ('foo' ~~ m{ (.) (.) })[*];                          # (「f」 「o」)
      say ('foo' ~~ m{ (.) (.) $<I'm-named>=(.) })<I'm-named>; # 「o」
      

Why the additional complexity? For Match objects it's a trade off to make the tremendous additional power and utility of general parsing automatically and easily available. See Extracting from .bib file with Raku for more discussion of this.

raiph
  • 31,607
  • 3
  • 62
  • 111
  • 2
    ... And Match objects are Captures, i.e., lists and associative at the same time. Coercing to list or anything that puts it in a list context will do. – jjmerelo Jan 31 '22 at 19:01
5

You'll never do wrong following Raiph's answers. But I'm going to try and explain a bit why that works, and propose alternatives. A Match is a Capture, a beast that's essentially a list and an associative array at the same time. What you want is to have the result as a list, same as it happens in Perl. How do you extract the "list" part (or coerce it to a list)? Easy: use explicit coercion (as Raiph suggests) or try and put it in a list context. What creates a list context? Flattening does:

my ($a, $b, $c, $d, $e) = |('hello' ~~ m{ ^(h) (e) (l) (l) (o) });

List binding does too:

my ($a, $b, $c, $d, $e) := 'hello' ~~ m{ ^(h) (e) (l) (l) (o) };

The thing is that every one of the variables will still contain a Match; what you probably want is the self same thing as in Perl, a list of strings. We can get that with this combo:

my @array is Array[Str(Match)] = | ('hello' ~~ m{ ^(h) (e) (l) (l) (o) });

Where we get the list context in the right hand side, and by explicitly declaring an array with coercing elements, we get [h e l l o] as a result.

Dan Bron
  • 2,313
  • 1
  • 22
  • 35
jjmerelo
  • 22,578
  • 8
  • 40
  • 86