http://qs1969.pair.com?node_id=11137057

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I would like to use the ".." as a loop operator but in a string. Is there any simple perl-ish way I can accomplish this? For some reason, I thought perl would support this, but it doesn't.
my $arr=[1,2,3,4,5,6,7]; my $loop="2,4..5"; splice @$arr,$_,0,999 foreach($loop);

I want $arr to be [1, 2, 999, 3, 999, 999, 4, 5, 6, 7]. This works fine if you pass in 2,4..5 instead of "2,4..5". I notice that '2', '4'..'5' will also work, but when the .. operator is within string, it does not.

Thank you for your time!

Michael

Replies are listed 'Best First'.
Re: loop iterator in a string
by haukex (Archbishop) on Sep 27, 2021 at 18:46 UTC

    If you don't mind using a dash instead of two dots, you might be interested in Set::IntSpan. See the example of its next method in the Synopsis for how to interate through the set. Just don't use the indirect object syntax as it is shown in the documentation, i.e. write Set::IntSpan->new instead of new Set::IntSpan, use $set->insert($n) instead of insert $set $n, and so on.

      I absolutely love this idea. Thank you for the suggestion!
Re: loop iterator in a string
by tybalt89 (Monsignor) on Sep 27, 2021 at 21:39 UTC

    For the evalphobic...

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11137057 use warnings; my $arr=[1,2,3,4,5,6,7]; my $loop="2,4..5"; splice @$arr,$_,0,999 foreach map { /\.\./ ? $` .. $' : $_ } split /,/ +, $loop; use Data::Dump 'dd'; dd $arr;

    Outputs:

    [1, 2, 999, 3, 999, 999, 4 .. 7]
Re: loop iterator in a string
by LanX (Saint) on Sep 27, 2021 at 18:33 UTC
    the "simple" way is using eval

    DB<53> say for eval "2,4..9" 2 4 5 6 7 8 9

    NB: this might lead to problems with large intervals though, because foreach can't tell when to iterate lazily. But good enough if you don't intend to scale large.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      Oh that's brilliant Rolf! I totally forgot about eval. This is definitely good enough for my use case. Thank you!

        Please be aware that eval with anything other than a fixed, literal string (i.e. no variables interpolated in) has the potential to introduce security issues or other subtle bugs.

Re: loop iterator in a string
by BillKSmith (Monsignor) on Sep 27, 2021 at 18:49 UTC
    This is pretty close to what you want. Use eval to evaluate the operators in the string.
    use strict; use warnings; my $arr=[1,2,3,4,5,6,7]; my $loop="2,4..5"; splice @$arr,$_,0,999 foreach(eval $loop); $, = ' '; print @$arr

    OUTPUT:

    1 2 999 3 999 999 4 5 6 7
    Bill
Re: loop iterator in a string
by LanX (Saint) on Sep 28, 2021 at 15:45 UTC
    > I would like to use the ".." as a loop operator but in a string.

    Does it really need to be a string?

    What about a functional solution to store intervals?

    DB<83> $loop = sub {2,4..5} DB<84> say for &$loop 2 4 5 DB<85>

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery