Skip to content

Clarify range's exclusivity. #15217

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

Merged
merged 1 commit into from
Jul 22, 2014
Merged

Clarify range's exclusivity. #15217

merged 1 commit into from
Jul 22, 2014

Conversation

steveklabnik
Copy link
Member

/// Returns an iterator over the given range, starting with `start` and ending
/// at `stop`.
///
/// The range is inclusive with regard to `start`, and exclusive with regard to
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this really explains the full rationale (although I'm not sure how much API docs can or should explain rationale, since the goal of API docs is to learn how to use them rather than understand their design principles). Starting at zero is really a special case of the more general point that half-open ranges compose cleanly. For example,

for n in range(0, 10u) { f(n); }

is equivalent to

for n in range(0, 6u) { f(n); }
for n in range(6u, 10u) { f(n); }

Edit: Fixed an unbelievably bad bug in the example, which is actually the whole point! Using literals probably doesn't demonstrate the composability that well since you could always just pick different literals. The critical point, which I botched at first, is that you use the same single number to divide up the interval without having to do any arithmetic. Formally, given a half-open range [a, b), you can take any i in the range and [a, b) is equivalent to [a, i) o [i, b). Commonly this shows up when picking, say, a mid-point in a divide-and-conquer algorithm:

let mid = ...;
for n in range(start, mid) { ... }
for n in range(mid, end) { ... }

Copy link
Member Author

Choose a reason for hiding this comment

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

Ahhhh interesting.

I do think that rationale is good, because it helps you build the mental model for how the API is intended to be used.

@mdinger
Copy link
Contributor

mdinger commented Jun 27, 2014

The [start, stop) notation is useful. It'll probably appear elsewhere anyway so you might want to keep it.

Here I tried a different approach though if you will want an example like this here I'm not sure:

// [0,3] -> 0,1,2,3 -> count from 0 to 3 including `[]` 0 and 3
// (0,3) ->   1,2   -> count from 0 to 3 excluding `()` 0 and 3
// (0,3] ->   1,2,3 -> combo

// So:
// [0,7) -> 0,1,2,3,4,5,6
// [0,3) -> 0,1,2,        -> ends at 3
// [3,7) ->       3,4,5,6 -> also starts at 3

// Whereas:
// [0,6] -> 0,1,2,3,4,5,6
// [0,2] -> 0,1,2,        -> ends at 2
// [3,6] ->       3,4,5,6 -> starts at 3 which is different from 2
// Which means with `[start,stop]`, you'll always have to work harder to align ranges
// because they don't start and end at the same point

// It also means:
// [2,6) -> 2,3,4,5 -> has 4 (6-2) elements
// [2,5] -> 2,3,4,5 -> has 4 (5-2+1) elements

// [612, 5244) -> how many elements?

Questions regarding this notation will probably come up often with new programmers and people used to one based indexing.

@steveklabnik
Copy link
Member Author

That's not bad.

@learnopengles
Copy link

I would agree that keeping the original like with the [start, stop) notation and following that up with further explanation would be useful. I also liked the note above "over the range [start, stop) (starting at start (inclusive), and ending at stop (exclusive))."

How easy is it to get to this page? My first points of contact were with the tutorial (http://doc.rust-lang.org/tutorial.html) and the reference (http://doc.rust-lang.org/rust.html). I think it could be worth also clarifying the aspects of range in those docs as well, in terms of a couple of examples and a mention about the exclusive nature of the second parameter.

@thestinger
Copy link
Contributor

There's a separate iterator tutorial where extensive coverage of the various range functions and count would be nice. I think the tutorial should just show one simple for loop example and link to that guide. The language reference shouldn't include anything about the standard library, the API documentation is the reference for that. It just needs to document the for loop semantics in depth.

@kwantam
Copy link
Contributor

kwantam commented Jul 2, 2014

Perhaps a link to Edsger Dijkstra's classic explanation, why numbering should start at zero, is appropriate? I'm sure readers of the documentation will appreciate such enhancement of their erudition. :)

@steveklabnik
Copy link
Member Author

I've updated the wording, even though I said @huon rather than @huonw 😢 . Will get rebased away anyway. Sorry @huon!

What do we think of a non-array example? Or is this okay?

@bors bors merged commit ba769d8 into rust-lang:master Jul 22, 2014
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 21, 2023
internal: convert unwrap to except and add a debug log

Remove an unsafe unwrap that can cause crashes if the value is a `SendError`.

This is my first PR on this repo, please let me know if there is anything I can improve or details I can provide.
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.