Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I count up in Perl 6 with a sequence or a range?

Tags:

range

seq

raku

Perl 6 has lazy lists, but it also has unbounded Range objects. Which one should you choose for counting up by whole numbers?

And there's unbounded Range with two dots:

0 .. *

There's the Seq (sequence) with three dots:

0 ... *

A Range generates lists of consecutives thingys using their natural order. It inherits from Iterable, but also Positional so you can index a range. You can check if something is within a Range, but that's not part of the task.

A Seq can generate just about anything you like as long as it knows how to get to the next element. It inherits from Iterable, but also PositionalBindFailover which fakes the Positional stuff through a cache and list conversion. I don't think that a big deal if you're only moving from one element to the next.

I'm going back and forth on this. At the moment I'm thinking it's Range.

like image 307
brian d foy Avatar asked Oct 12 '16 20:10

brian d foy


2 Answers

Semantically speaking, a Range is a static thing (a bounded set of values), a Seq is a dynamic thing (a value generator) and a lazy List a static view of a dynamic thing (an immutable cache for generated values).

Rule of thumb: Prefer static over dynamic, but simple over complex.

In addition, a Seq is an iterable thing, a List is an iterable positional thing, and a Range is an ordered iterable positional thing.

Rule of thumb: Go with the most generic or most specific depending on context.

As we're dealing with iteration only and are not interested in positional access or bounds, using a Seq (which is essentially a boxed Iterator) seems like a natural choice. However, ordered sets of consecutive integers are exactly what an integer Range represents, and personally that's what I would see as most appropriate for your particular use case.

When there is no clear choice, I tend to prefer ranges for their simplicity anyway (and try to avoid lazy lists, the heavy-weight).

Note that the language syntax also nudges you in the direction of Range, which are rather heavily Huffman-coded (two-char infix .., one-char prefix ^).

like image 68
Christoph Avatar answered Nov 11 '22 00:11

Christoph


Both 0 .. * and 0 ... * are fine.

  • Iterating over them, for example with a for loop, has exactly the same effect in both cases. (Neither will leak memory by keeping around already iterated elements.)
  • Assigning them to a @ variable produces the same lazy Array.

So as long as you only want to count up numbers to infinity by a step of 1, I don't see a downside to either.

The ... sequence construction operator is more generic though, in that it can also be used to

  • count with a different step (1, 3 ... *)
  • count downwards (10 ... -Inf)
  • follow a geometric sequence (2, 4, 8 ... *)
  • follow a custom iteration formula (1, 1, *+* ... *)

so when I need to do something like that, then I'd consider using ... for any nearby and related "count up by one" as well, for consistency.

On the other hand:

  • A Range can be indexed efficiently without having to generate and cache all preceding elements, so if you want to index your counter in addition to iterating over it, it is preferable. The same goes for other list operations that deal with element positions, like reverse: Range has efficient overloads for them, whereas using them on a Seq has to iterate and cache its elements first.
  • If you want to count upwards to a variable end-point (as in 1 .. $n), it's safer to use a Range because you can be sure it'll never count downwards, no matter what $n is. (If the endpoint is less than the startpoint, as in 1 .. 0, it will behave as an empty sequence when iterated, which tends to get edge-cases right in practice.)
    Conversely, if you want to safely count downwards ensuring it will never unexpectedly count upwards, you can use reverse 1 .. $n.
  • Lastly, a Range is a more specific/high-level representation of the concept of "numbers from x to y", whereas a Seq represents the more generic concept of "a sequence of values". A Seq is, in general, driven by arbitrary generator code (see gather/take) - the ... operator is just semantic sugar for creating some common types of sequences. So it may feel more declarative to use a Range when "numbers from x to y" is the concept you want to express. But I suppose that's a purely psychological concern... :P
like image 35
smls Avatar answered Nov 11 '22 02:11

smls