-
-
Notifications
You must be signed in to change notification settings - Fork 71
Add a form of “descending ranges” #747
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
a09c119 to
4419da9
Compare
|
This is precisely the operator names that @dgcosta2 used here https://github.com/dgcosta2/matrix/blob/main/operators.rhm so that seems like a good sign. |
|
This looks great!
Having all of |
|
I see that |
|
Explicit invocations of Having both I wasn’t very sure about the design of |
Ah, right — I think that's how I had understood it previously, and forgot. We should write something like this in the documentation I also like the ideas of having |
Previously, only `..` and `..=` ranges were sequences/listables, on the grounds that such a range has a definite first element, namely the included starting point. (And, more importantly, because the precedents, Rust and Racket, didn't include `<..`- or `<..=`-like ranges.) I worried that there might be confusion regarding the first element of a `<..` or `<..=` range, but it seems that making the first included integer the first element is fine. Moreover, this means that a `<..` or `<..=` range would produce the same sequence/list as the canonicalized range.
A "descending range" isn't actually a range, but is merely created for the purpose of producing range-like sequences in descending order. Since their purpose is for producing sequences, there are six forms in total, each of which corresponds to one of the sequence range forms. They are: - `start >=.. end`, which corresponds to `start .. end` - `start >=..= end`, which corresponds to `start ..= end` - `start >=..`, which corresponds to `start ..` - `start >.. end`, which corresponds to `start <.. end` - `start >..= end`, which corresponds to `start <..= end` - `start >.. end`, which corresponds to `start <.. end` Each of the names starts with `>`, and I tried to keep with the convention that `=` at the end indicates inclusiveness. The forms only serve as expressions, not as bindings, since they shouldn't work as general range objects. They all produce objects that satisfy `DescendingRange`, which isn't a subclass of `Range`. A `DescendingRange` can be used directly or with `.step_by` in `for`, and will be optimized like its `SequenceRange` counterpart. A `ListRange` can be turned into a `DescendingRange` with `.descending`, and the optimization cooperates with it, too. So, for example, `(0..5).descending().step_by(-2)` will be inlined. Note also that `DescendingRange.step_by` takes an negative integer step, unlike `SequenceRange.step_by`.
These are the possible results of `ListRange.descending`, which means that `[& (0..5).descending()]` now works as expected.
4419da9 to
f444458
Compare
|
Updated to incorporate the suggestions, including |
|
This is really great work — thanks! LGTM |
This PR addresses the lack of range-like sequences in descending order, as previously discussed on Discord. In summary:
<..and<..=ranges with a starting point are now{Sequence,List}Range;ListRange.descendingproduces (listable) descending ranges.Methods that produce sequences are as follows:
Descending ranges are of the following forms, each corresponding to a sequence range form:
Descending ranges satisfy
DescendingRange, which is not a subclass ofRange. They only serve as expressions, not as bindings. Among them, listable ones also satisfyDescendingListRange, which offers a.to_listimplementation.Moreover,
(rge :: ListRange).descending()also produces a descending range (more preciselyDescendingListRange), and optimization in implicit.to_sequenceand dot.step_bycooperate with it. This means that(0..5).descending().step_by(-2)as a sequence is specially inlined.