Skip to content

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

Closed
wants to merge 1 commit into from
Closed

Add Interleave iterator #15886

wants to merge 1 commit into from

Conversation

Gankra
Copy link
Contributor

@Gankra Gankra commented Jul 21, 2014

@sfackler was interested in having this adapter, so I hacked it together.

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 };
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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).

Copy link
Contributor Author

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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?

@Gankra
Copy link
Contributor Author

Gankra commented Jul 22, 2014

@kballard I've incorporated your recommendations, and fixed the errors. I didn't fully inline all the as uints because I found it increased line length and paranthesization in a way that reduced overall readability. I'll fully inline them if still desired, though.

@liigo
Copy link
Contributor

liigo commented Jul 22, 2014

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 {
Copy link
Contributor

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 {
    ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call.

@lilyball
Copy link
Contributor

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.

@Gankra
Copy link
Contributor Author

Gankra commented Jul 23, 2014

@kballard I've made a retroactive RFC: rust-lang/rfcs#180

@Gankra
Copy link
Contributor Author

Gankra commented Jul 23, 2014

RFC killed, downgraded to pesudo-rfc on discuss: http://discuss.rust-lang.org/t/pseudo-rfc-interleave-iterator/249

@Gankra
Copy link
Contributor Author

Gankra commented Jul 23, 2014

@cmr seems to be giving this the thumbs up, concept-wise.

@Gankra
Copy link
Contributor Author

Gankra commented Jul 23, 2014

Rebased. @kballard: r?

@brson
Copy link
Contributor

brson commented Jul 24, 2014

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?

@Gankra
Copy link
Contributor Author

Gankra commented Jul 24, 2014

@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

@lilyball
Copy link
Contributor

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 libiterators library that people can include via cargo to hold the more esoteric things like interleave. Although offhand I don't know what else to put in there.

@liigo
Copy link
Contributor

liigo commented Jul 24, 2014

I'm skeptical of the value of having this in std.

+1, it's not very useful

@brson
Copy link
Contributor

brson commented Jul 25, 2014

@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 brson closed this Jul 25, 2014
@Gankra
Copy link
Contributor Author

Gankra commented Jul 25, 2014

@brson no worries, I was going to close it in an hour or so myself, for the same reasons.

bors added a commit that referenced this pull request Aug 24, 2014
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).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants