Minimiscience wrote:
> On Oct 4, 2009, at 12:47 PM, yary wrote:
>> There was a big discussion about this on the list recently but I don't
>> recall the resolutions.
>
> The resolution was r28344: <http://dev.pugscode.org/changeset/28344>.
> The short version is that ranges are now primarily used for testing
> inclusion in intervals; if you want a list of values in an interval, use
> ... instead.

Jon Lang wrote:
yary wrote:
I'm confused between using ranges to generate a lazy list and using
them as criteria to match against.

Indeed.  It was my understanding that there was a recent change to
Ranges so that they now exist primarily to be used as matching
criteria.  If you wish to generate a list, the preferred approach
these days is the ... infix operator:

    1 .. 100 # the range of values between 1 and 100, inclusive.
    1, 2 ... 100 # a list of integers.

The ability to generate a lazy list using a Range object is now of
secondary importance, and should not be a required feature anymore.
In particular, :by was removed from Range.

What Minimiscience and Jon Lang stated has been my understanding as well, especially since the r28344 resolution. A Range is primarily used as an interval, either to simply represent a span of values of some orderable type (which could be any type at all in the general case), or to test whether a given other value is orderable between the interval's endpoints. And this is all that I want to use it for, in a general context that is orthogonal to type. So supporting .succ() or .prec() in the general case isn't needed.

Now, it turns out that Synopsis 3 was the place with some of the answers I 
sought:

  http://perlcabal.org/syn/S03.html#Range_and_RangeIterator_semantics

For example, .min and .max are used to read the declared endpoint values of a 
Range.

However, I still don't see how one would retrieve the distinction between say "1..10" and "1^..^10". I suggest that an extra 2 methods such as .min_is_outside and .max_is_outside (each returns a Bool) could fit the bill, and in fact since I have Pugs write access I think I'll go make that addition myself in the above S03 section.

Now I was going to ask how to represent endpoints that are "whatever" if "whatever" is orthogonal to type, but then I realized the answer is simply to use a Whatever object, which is one of the 4 "Undefined types" mentioned in S02.

For example, if someone said:

  my $r = $foo..*;
  my $min = $r.min;  # $foo's value
  my $max = $r.max;  # Whatever.new()

Now maybe it would be reasonable for .max to return +Inf if $foo was an Int, but I would expect that for any type where $foo doesn't have a concept of positive-infinity, a * would just be Whatever.new() by default.

On a tangent, I was thinking that if Range really is meant to represent an interval in its general case, which is orthogonal to type, then Range should be as generic as Set or other element-type-orthogonal containers, and also support not only the Iterable role but the Associative role, like Set does.

You see, conceptually an interval is a set of values, where the member values are defined not in terms of an enumeration (as with Set, Bag, PairValSet, etc) but rather in terms of what values exist from the value domain of the interval's endpoints that are ordered between those endpoints.

And so, conceptually "$a ~~ 1..10" is a set membership test, and I think it would be reasonable to be able to use the more semantics-specific operators that one uses on Set or Hash or whatever to test membership, on a Range; for example:

  $val ∈ Set.new( 42, 27, 4, 36 )
  $val ∈ 20^..40

Similarly, there should be operators or methods for testing if 2 Range overlap, or if one is contained in the other, or to derive 1 from 2 using intersection or union etc.

These are operations common with mathematical intervals (those over Real say), but they are orthogonal to type.

It is more just using + or - etc which are specific to the maths, or rather they aren't orthogonal to type but just are for types that support +/-/etc.

On a tangent, if there is any thought to make S32/Temporal have specific support for Instant/DateTime interval objects (which are *not* the same meaning as durations), I would say that a suitably generic Range should fit the bill by itself, as far as declaring the objects goes. For example, "Range of Instant" or "Range of DateTime" should be a sufficient type declaration for a date range type, rather than needing to come up with something special, unless that special thing is just an alias for the above.

So those are some thoughts.  I probably have more.

-- Darren Duncan

Reply via email to