killercup / a-range Goto Github PK
View Code? Open in Web Editor NEWWrite quick and explict ranges in Rust
Home Page: https://docs.rs/a-range
License: Apache License 2.0
Write quick and explict ranges in Rust
Home Page: https://docs.rs/a-range
License: Apache License 2.0
Either the crate-level or the Range docs should describe how to write a custom type that can be used as an index. (This will require you to impl num_traits::One
for the custom type, for example.)
from(n).up_to(n-1)
should failfrom(n).down_to(n+1)
should failfrom(n).up_to(n)
and from(n).down_to(n+1)
do? Nothing?Proptest is a great property testing framework. We should use it to assert some of the features of this crate.
Inspired by #5 (comment)
To understand how Range::
work, it helps to see example code in the documentation. These examples should also work as doc tests (you can liberally hide the assertion lines if you want).
Add at least one example to
Range::as_std_range()
Range::as_std_range_inclusive()
Into<std::ops::Range<Idx>> for Range
Into<std::ops::RangeInclusive<Idx>> for Range
Currently, there are these unit tests:
Lines 371 to 391 in ce391ed
You can move this code into the doc tests, and remove these unit tests afterwards.
Add methods to convert the internal Range structure to the ones present in std::ops.
Make this work:
let x = a_range::from(4).up_to_infinity();
let some_numbers: Vec<i32> = x.into_iter().take(100).collect();
for i in a_range::from(1).up_to(5).iter() { let _i: &i32 = i; }
compilesiter()
method::From
should have Copy semantics or Traits available (either derived or implemented by us).
Since multiple ranges can have a single starting point, it makes sense for a user to be able to reuse a ::From
object.
An example:
let start = a_range::from(10);
let up_range = start.up_to(13); // [10, 11, 12, 13]
let down_range = start.down_to(8); // No copy semantics, so this fails to compile.
Formally, this is the kind of compile error I get right now:
error[E0382]: use of moved value: `x`
--> src/lib.rs:27:18
|
6 | let up_range = x.up_to(10);
| - value moved here
7 | let down_range = x.down_to(10);
| ^ value used here after move
|
= note: move occurs because `x` has type `a_range::From<i32>`, which does not implement the `Copy` trait
Having Direction
avaliable publicly means that this library could be used in situations where there are more than one dimension. The following is a contrived example:
struct Vector2 { x: u32, y: u32 };
struct Diagonal45Deg;
impl Direction<Vector2> for Diagonal45Deg {
fn step(i: &mut Vector2) {
*i.x += 1;
*i.y += 1;
}
}
fn main() {
let range = a_range::from(Vector2 { 0, 1 }).to_diag(Vector2 { 10, 11 });
}
The example above is not fully functional because we have not defined how two Vector2
should be compared (discussed below), but I just wanted to show an example usage.
A difficulty with multiple dimensions is defining when a range should end. When there is only a single dimention, its easy to check if a value is greater/smaller than another and make conclusions based on that. E.g one is not allowed to do a_range::from(5).to(0)
because 5 > 0
. Using multidimensional directions the destination might be harder to define because of multiple conditions. With the current implementation we need to define some way of comparing two Vector2
, which can be done in multiple ways. In this situation we probably want to compare the magnitude. However this would lead to the following being a valid range a_range::from(Vector2 { 1, 1 }).to_diag(Vector2 { -2, -2 })
because the magnitude of the second Vector2
is still larger than the initial, despite it pointing in the opposite direction.
This could be solved by rather having a signature like a_range::from(Vector2 { 1, 1 }).take_diag(5)
, which would generate a range which gives back 5 vectors. This is already, in a sense, a part of the library using up_to_infinity
followed by a .iter().take(5)
. I think it would make the library more generic to rather use a countdown-field than the current to
field, especially if adding multidimensional ranges.
This might be an ambitious addtion which makes the library perhaps a bit too generic. Maybe then adding this library would be "harder" than just manually implementing a special iterator which performs the given task.
Thoughts/Comments?
We recently added these docs:
Lines 54 to 58 in ce391ed
This behavior is tested in this unit test:
Lines 393 to 397 in ce391ed
It is also possible for this to become a doc test (as I've just found out), which would make this more visible.
fail_up_to_invalid_range
and fail_down_to_invalid_range
tests into doc testsRange
s implement collect()
and to_vec()
methods. To illustrate how they can be used, we should add examples to their documentation. These examples should also work as doc tests for the methods.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.