Infinite, cycling sequences

My Tie::Cycle Perl 5 module is almost trivial but it solved a customer problem a long, long time ago. It’s makes a list that looks like a scalar. Every time you access the scalar you get the next value in the list (wrapping around at the end).

How would I do the same thing in Perl 6? I started thinking about a way to make a sequence whose elements were always True, infinitely and forever. I fell back on the idea of cycling through a list:

my $colors := make-cycle( <red green blue> );

for $colors {
	put $_;
	last if $++ > 5;
	}

sub make-cycle ( *@a --> Seq ) {
	{ @a[ $++ % * ] } ... Inf
	}

It loops through all of the colors:

red
green
blue
red
green
blue
red

I could have done the same thing with other lists that would cycle forever. Even the trivial list of one item might be useful. This is what I wanted when I started playing with this:

my $false       := make-cycle( False );
my $true        := make-cycle( True  );
my $true-false  := make-cycle( True, False );
my $false-true  := make-cycle( False, True );

The ... is the sequence operator. You can use some code to decide what comes next. That includes deciding what comes first. I want to grab the next element of the array. That’s easy. Keep a cursor of the index and add to each each time I grab to something. When it gets too big reset it to the beginning.

Perl 6 has nice syntax for this. All that is in $++ % * that I use for the index in @a[ ]. I need a variable to act as the cursor. I don’t need it anywhere else than inside the array indexing operator.

The $ by itself is an anonymous scalar variable that allows you to skip the declaration; the variable shows up exactly once because that’s how many times I need it. The ++ is the auto-increment operator to move the cursor along.

The value in $ eventually passes the last index of the list. The modulus operator % brings it back in that range. For a list of 5 items, the first item is list is at indices 0, 5, 10, and so on. Those are all effectively 0 modulo the number elements.

The * is the Whatever star. What that does depends on where it shows up. In the array indexing operator it’s the number of elements (not the last index) in the thingy. That’s the same number I need for the modulus.

All together that’s the cryptic $++ % *. It’s a bit tricky to read but I typically don’t start writing code like that unless I’ve done it before. I do it the long way.

I don’t even need the make-cycle factory (although it’s convenient to forget how this works). I don’t think I’d want this all over my code even if I can do it:

my $seq := { ( <red green blue> )[ $++ % * ] } ... Inf;

Even then, Seq.from-loop already does most of the work. I don’t need to use ... because this keeps going by always calling the block of code to get the next value:

my $seq := Seq.from-loop: { ( <red green blue> )[ $++ % *] };

It could be a module but this isn’t node.

4 comments

  1. There is actually an idiom in Perl 6 for infinite recycling sequences. Basically Slip xx *:

    .say for |<red green blue> xx *; # red green blue red green blue….
    

Leave a Reply to brian d foy Cancel reply

Your email address will not be published. Required fields are marked *