Athanasius has asked for the wisdom of the Perl Monks concerning the following question:
In Perl, a range within an array slice behaves as though the individual elements in the range had been specified with comma separators:
11:44 >perl -MData::Dump -we "my @c = 'a'..'z'; dd map { qq[<$_>] } @c
+[6..9, 23, 25];"
("<g>", "<h>", "<i>", "<j>", "<x>", "<z>")
11:45 >
This is what I would expect. But in Raku, it seems that a range inside an array slice produces an additional layer of grouping:
11:45 >raku -v
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
11:45 >raku -e "my @c = 'a'..'z'; @c[6..9, 23, 25].map( { qq[<$_>] } )
+.raku.put;"
("<g h i j>", "<x>", "<z>").Seq
11:46 >
AFAICT, the Raku documentation on subscripts doesn’t explain this. So, I have two questions:
- What is the cause of this (to me) strange behaviour? (Is it a feature or a bug?)
- How can I use ranges in Raku array slices to achieve the same result I get in Perl (i.e., no additional grouping)?
Thanks,
Re: [Raku] Ranges in array slices
by holli (Abbot) on Jun 01, 2021 at 05:47 UTC
|
Not a bug, just a misunderstanding about how Iterables (Lists, Ranges, etc) work in Raku: Namely they do not automatically flatten.
.WHAT.say for 6..9, 23, 25; # (Range) (Int) (Int)
.WHAT.say for flat 6..9, 23, 25; # (Int) (Int) (Int) (Int) (Int) (Int)
holli
You can lead your users to water, but alas, you cannot drown them.
| [reply] [d/l] |
|
Hello holli,
Thanks, that’s brilliant!
Note for my fellow Raku-challenged monks: My first thought on seeing holli’s code was that flat was taking the range 6..9 as its argument. But, of course, the argument to flat here is the whole comma-separated list: 6..9, 23, 25. So the following constructs both solve my problem:
16:21 >raku -e "my @c = 'a'..'z'; @c[flat 6..9, 23, 25].map( { qq[<$_>
+] } ).raku.put;"
("<g>", "<h>", "<i>", "<j>", "<x>", "<z>").Seq
16:21 >raku -e "my @c = 'a'..'z'; @c[ (6..9, 23, 25).flat ].map( { qq[
+<$_>] } ).raku.put;"
("<g>", "<h>", "<i>", "<j>", "<x>", "<z>").Seq
16:22 >
Thanks again,
| [reply] [d/l] [select] |
Re: [Raku] Ranges in array slices
by tomasz (Acolyte) on Jun 05, 2021 at 05:25 UTC
|
You can apply a sequence here:
> my @c = 'a'..'z'; @c[6...9, 23, 25].map( { qq[<$_>] } )
(<g> <h> <i> <j> <x> <z>)
It has the advantage of working downwards also:
> my @c = 'a'..'z'; @c[9...6, 23, 25].map( { qq[<$_>] } )
(<j> <i> <h> <g> <x> <z>)
You have to be careful with this by ranges:
> my @c = 'a'..'z'; @c[9..6, 23, 25].map( { qq[<$_>] } )
(<> <x> <z>)
| [reply] [d/l] [select] |
|
Thanks tomasz, and a belated welcome to the Monastery!
The sequence operator looks really powerful: my attention was particularly caught by this example from the documentation:
This allows you to write
say 1, 1, * + * ...^ *>= 100;
# OUTPUT: «(1 1 2 3 5 8 13 21 34 55 89)»
to generate all Fibonacci numbers up to but excluding 100.
Of course, now that I have an operator that works the way I expected the range operator to work, I’m wondering: why would I ever need the range operator?
Cheers,
| [reply] |
|
| [reply] [d/l] [select] |
|
Hi there!
I'm not so sure, to be honest. I'm still very fresh with Raku.
From what I've gathered so far, you'll take range when you just need two ends of a stick, and sequence, when you need the stick.
EDIT:
Sequence can also be characterised by the accented stickiness of the stick, to continue this sticky metaphor. It's accented even over the idea of its end, to the effect that if an end of the stick doesn't meet the stickiness, then it's ignored. Example:
0, * + 2 ... 1
See, where it goes?
I wonder if it's grammatically possible to jump over both ends this way... (sic!)1
1) ...like this... | [reply] [d/l] |
|
|
|
|
|
|
|