Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

[Raku] Ranges in array slices

by Athanasius (Archbishop)
on Jun 01, 2021 at 02:08 UTC ( [id://11133342]=perlquestion: print w/replies, xml ) Need Help??

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:

  1. What is the cause of this (to me) strange behaviour? (Is it a feature or a bug?)
  2. How can I use ranges in Raku array slices to achieve the same result I get in Perl (i.e., no additional grouping)?

Thanks,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
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.

      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,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

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>)

      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,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Functionally you can express all Ranges as Sequences, albeit that'd be slower methinks. What you're asking is a bit like asking why we need multiplication if we can just keep adding.

        Check out the documentation. Range, just like List does Positional and Iterable roles. Seq only does Iterable and implements the indexing (AT-POS method et. al) itself, specifically a Seq always has to calculate all n-1 elements before you can access the n-th element.


        holli

        You can lead your users to water, but alas, you cannot drown them.
        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...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11133342]
Approved by kcott
Front-paged by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (10)
As of 2024-04-18 12:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found