-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add Interleave iterator #15886
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
Add Interleave iterator #15886
Conversation
let (b_lower, b_upper) = self.b.size_hint(); | ||
|
||
// for capturing offset for whether the "head" points at a or b | ||
let off_by_one = if self.using_first { 1u } else { 0u }; |
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.
Fun fact: you can just say let off_by_one = self.using_first as uint;
. Booleans can coerce to all primitive integral types.
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.
Neat! Would you recommend this from a clarity point of view?
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.
It's a bit simpler, and avoids a conditional (which presumably would get optimized away anyway but w/e).
It may actually be beneficial to not even do the conversion here but instead just keep the boolean a boolean and convert it where you actually need the integral value (e.g. that way 1 - off_by_one
just becomes !using_first as uint
).
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.
All else equal, I think off_by_one captures intent a bit better. I was a bit cagey about having this trick in the code at all, because it makes things a bit harder to read, in my mind. It's a big code reduction win, though. I'll yield to your expertise on the matter, though.
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.
Hmm... having as uint everywhere seems to be seriously dropping readability for me, are you sure?
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.
Everywhere? How often do you need it?
@kballard I've incorporated your recommendations, and fixed the errors. I didn't fully inline all the |
Is this useful enough to be in lib std? |
fn next(&mut self) -> Option<A> { | ||
self.using_first = !self.using_first; | ||
// this is backward on purpose; variable name is always accurate wrt to *next* read | ||
if !self.using_first { |
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.
You can ditch the comment by using a local variable.
let use_a = self.using_first;
self.using_first = !use_a;
if self.use_a {
...
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.
Good call.
At this point I think it LGTM, although the commits need to be squashed together. Also, I'm not going to unilaterally decide that this is indeed appropriate to put in the standard library. If someone else agrees that this is good, then r=me with the commits squashed. |
@kballard I've made a retroactive RFC: rust-lang/rfcs#180 |
RFC killed, downgraded to pesudo-rfc on discuss: http://discuss.rust-lang.org/t/pseudo-rfc-interleave-iterator/249 |
@cmr seems to be giving this the thumbs up, concept-wise. |
Rebased. @kballard: r? |
I'm skeptical of the value of having this in std. We have many iterators already, some of questionable utility. Does anybody have a sense of how common this is? |
@brson: as far as I can tell from a cursory search of functional languages that I know the name of, it seems nonexistant as a std adapter. But I'm not an expert on functional languages, and I find their docs to be fairly tedious to search. Although maybe this sort of thing is easier to implement in more functional languages? Or maybe they just don't care about things like random access, size, and bi-directionality, which is what makes it non-trivial. I don't have a lot to say about its usefulness that I haven't already. A couple people expressed a desire for it, and it's non-trivial for someone to implement a full version (not just a plain Iterator) correctly. I personally don't need it for anything, I wrote it because it seemed like an interesting learning project. Perhaps @sfackler or someone in the thread can provide a more rigorous argument for its inclusion. Honestly, at this point my primary motivation to get it in is just to not have wasted the ever-patient and helpful @kballard's time. :D |
I don't have much of an opinion as to whether it's worth having in the standard library. If not, perhaps @gankro could start a |
+1, it's not very useful |
@gankro, I'm going to close this on the assumption that it isn't generally useful enough to provide to everybody by default (we have to worry about long-term bloat caused by maintaining features forever). Thank you for the contribution though. |
@brson no worries, I was going to close it in an hour or so myself, for the same reasons. |
Use ExactSize::len() and defer to its decisions about overly defensive assertions. Remove the length double-check and simply put a failure case if the Zip finds an uneven end in .next_back(). Fixing this up since I think I wrote this, and it's been known to confuse rusties (PR #15886).
@sfackler was interested in having this adapter, so I hacked it together.