-
Notifications
You must be signed in to change notification settings - Fork 199
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
More LineString iterators #705
Conversation
c690c41
to
ee28a36
Compare
Hitherto, we only supported looping as opposed to direct iteration (though since .0 is public, we could access the underlying vector anyway) This allows explicit (mutable) iteration via a CoordinatesIter struct
87ca144
to
476a6cf
Compare
Can |
Done. I don't think there's a way to leverage it for |
Co-authored-by: Corey Farwell <coreyf@rwell.org>
Implemented all yr suggestions @frewsxcv. |
geo-types/src/line_string.rs
Outdated
pub fn points_iter(&self) -> PointsIter<T> { | ||
PointsIter(self.0.iter()) | ||
} | ||
|
||
/// Return the coordinates of a `LineString` as a `Vec` of `Point`s | ||
/// Return an iterator yielding the members of a [`LineString`] as [`Coordinate`]s | ||
pub fn iter(&self) -> impl Iterator<Item = &Coordinate<T>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry to bikeshed on naming, but... iter
strikes me as a little off.
In contrast, these usages of iter
all make sense to me:
multi_point.iter() -> impl Iterator<Item = &Point<T>>
multi_line_string.iter() -> impl Iterator<Item = &LineString<T>>
multi_polygon.iter() -> impl Iterator<Item = &Polygon<T>>
vec_of_strings.iter() => -> impl Iterator<Item = &String>
For a collection of Foo
s, iter()
will yield Foo
. But I don't think of a LineString as a collection of Coordinates (it happens to look that way on disk, but so do all of our geometries).
What would you think of pub fn coords(&self)
or coords_iter()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn coords()
might match nicely with the existing:
/// Return an iterator yielding one [Line] for each line segment in the [`LineString`].
pub fn lines(&'_ self) -> impl ExactSizeIterator + Iterator<Item = Line<T>> + '_ { }
/// An iterator which yields the coordinates of a [`LineString`] as [Triangle]s
pub fn triangles(&'_ self) -> impl ExactSizeIterator + Iterator<Item = Triangle<T>> + '_ { }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm. I initially added iter() because I expected LineString to have it, mostly when writing internal code. But you're absolutely correct in that the choice stems purely from my own expectations, which are at least partly rooted in the fact that we had already added IntoIter so we could loop over Coordinates, and I was annoyed that we could loop but not explicitly iter().
I'm open to adding coords() instead, but should we then consider deprecating points_iter() in favour of points() in an effort to be consistent?
If we do, I'll probably rewrite the introductory docs a bit to note that we offer four iterators, but note that loops will yield Coordinate (which should be thought of as the default?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh geeze, software is so hard.
Honestly, in hindsight, I think it's a little weird that you can do this at all:
for x in &line_string {
...
}
But anyway, that ship sailed long ago, and maybe consistency is more important at this point. Thanks for bringing up the context, your change seems pretty reasonable in light of that.
Would it be crazy to do all of the following?
- Keep the
iter()
impl as you have it since it complements the existinginto_iter()
,- Alternatively, we could remove the into_iter impl from line_string, but I hesitate to break things, and I don't personally think it's doing much harm as is, just that there are clearer ways to write it.
- add
line_string.coords()
which does the exact same thing asline_string.iter()
but reads more clearly IMO - add points() / deprecate
points_iter()
- I think it's pretty idiomatic to omit the
_iter
suffix when returning transformations of the inner data - e.g.hash_map.values()
andhash_map.values_mut()
nothash_map.values_iter()
andhash_map.values_iter_mut()
same withstring.chars()
notstring.chars_iter()
.
- I think it's pretty idiomatic to omit the
I know it's a real laundry list of things... so if you're in spirit on board, but don't have the time to do it, feel free to punt on some of it.
Pulling #705 (review) comments out into the main thread for discussion. @michaelkirk I've diverged slightly from your suggestion: I've removed
I think I now prefer the lack of |
LGTM! I think this turned out rather nicely! Thanks for allowing the back-and-fourth. |
impl<T: CoordNum, IC: Into<Coordinate<T>>> FromIterator<IC> for LineString<T> { | ||
fn from_iter<I: IntoIterator<Item = IC>>(iter: I) -> Self { | ||
LineString(iter.into_iter().map(|c| c.into()).collect()) | ||
} | ||
} | ||
|
||
/// Iterate over all the [Coordinate](struct.Coordinates.html)s in this `LineString`. | ||
/// Iterate over all the [`Coordinate`]s in this [`LineString`]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for cleaning all these up!
I think so too! I'm gonna leave it open for a day in case anyone else wants to kick the tires, otherwise I'll merge tomorrow. |
bors try |
tryBuild succeeded: |
bors r+ |
Build succeeded: |
CHANGES.md
if knowledge of this change could be valuable to users.This PR adds the
iter
anditer_mut
methods onLineString
(previously only available via its public.0
field), yieldingCoordinate
s, and adds aninto_coordinates
method, complementinginto_points
. It also addsinto_iter
for borrowedLineString
s.Some of these methods overlap with those available in
geo
s CoordsIter trait, but:geo-types
library users are necessarilygeo
usersiter
methods is a constant papercut in my opinion.