Skip to content

Add get_opt to std::vec #9608

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
Oct 13, 2013
Merged

Add get_opt to std::vec #9608

merged 1 commit into from
Oct 13, 2013

Conversation

hmarr
Copy link
Contributor

@hmarr hmarr commented Sep 29, 2013

This adds get_opt to std::vec, which looks up an item by index and returns an Option. If the given index is out of range, None will be returned, otherwise a Some-wrapped item will be returned.

Example use case:

use std::os;

fn say_hello(name: &str) {
  println(fmt!("Hello, %s", name));
}

fn main(){
  // Try to get the first cmd line arg, but default to "World"
  let args = os::args();
  let default = ~"World";
  say_hello(*args.get_opt(1).unwrap_or(&default));
}

If there's an existing way of implementing this pattern that's cleaner, I'll happily close this. I'm also open to naming suggestions (index_opt?)

@bluss
Copy link
Member

bluss commented Sep 30, 2013

Ideally this method should not insert a boundary check for the vector indexing, so it would be implemented with unsafe code to achieve that (see unsafe_ref). RandomAccessIterator provides the same already for vectors, like this: args.iter().idx(1), but that trait is experimental-ish.

I think this is something that vec should provide. Either directly or through a RandomAccess trait.

@flaper87
Copy link
Contributor

flaper87 commented Oct 1, 2013

I think that get should be provided as well and should make the task fail if the index is not valid. See head & head_opt or last & last_opt.

Also, I don't think it should be implemented as an unsafe operation.

@huonw
Copy link
Member

huonw commented Oct 2, 2013

@flaper87 "v.get(i)" is v[i].

@flaper87
Copy link
Contributor

flaper87 commented Oct 2, 2013

@huonw yeah, I knew that. I should stop writing things when I'm falling asleep. Ignore the get thing. I still think get_opt shouldn't be unsafe, though.

FWIW, code looks good to me.

@bluss
Copy link
Member

bluss commented Oct 2, 2013

I didn't suggest it should be unsafe, only implemented internally with unsafe code. Vector indexing like v[i] always inserts bounds checks, which we want to avoid here since it is already done explicitly. LLVM hasn't optimized well enough to elide the bounds check before, but maybe it is recognized in this case. If it already optimizes well enough, unsafe code isn't needed.

@bluss
Copy link
Member

bluss commented Oct 2, 2013

Here is the unsafe idx_riced implementation and the safe idx implementation. They compile to the same IR in this case! Maybe I'm overly pessimistic about LLVM.

#[inline(never)]
fn idx_riced<'a, T>(v: &'a [T], i: uint) -> Option<&'a T> {
    if i < v.len() {
        unsafe {
            Some(std::cast::transmute(v.unsafe_ref(i)))
        }
    } else {
        None
    }
}

#[inline(never)]
fn idx<'a, T>(v: &'a [T], i: uint) -> Option<&'a T> {
    if i < v.len() {
        Some(&v[i])
    } else {
        None
    }
}

fn main() {
    let v = [1.0f32, 2.0, 3.0, 4.0];
    let x = idx(v, 7);
    let y = idx_riced(v, 7);
}

@flaper87
Copy link
Contributor

flaper87 commented Oct 2, 2013

@blake2-ppc I get what you mean, not quite sure why IR is the same for both, reducing the number of bound checks makes sense, nonetheless.

@hmarr
Copy link
Contributor Author

hmarr commented Oct 4, 2013

I just had a look at the IR and it does indeed appear to be equivalent. As that's the case it are you fine with leaving it in it's current state, as it's simpler than the unsafe implementation?

@bluss
Copy link
Member

bluss commented Oct 4, 2013

yes

@flaper87
Copy link
Contributor

flaper87 commented Oct 5, 2013

LGTM, @huonw r?

bors added a commit that referenced this pull request Oct 13, 2013
This adds `get_opt` to `std::vec`, which looks up an item by index and returns an `Option`. If the given index is out of range, `None` will be returned, otherwise a `Some`-wrapped item will be returned.

Example use case:

```rust
use std::os;

fn say_hello(name: &str) {
  println(fmt!("Hello, %s", name));
}

fn main(){
  // Try to get the first cmd line arg, but default to "World"
  let args = os::args();
  let default = ~"World";
  say_hello(*args.get_opt(1).unwrap_or(&default));
}
```

If there's an existing way of implementing this pattern that's cleaner, I'll happily close this. I'm also open to naming suggestions (`index_opt`?)
@bors bors closed this Oct 13, 2013
@bors bors merged commit 21b24e1 into rust-lang:master Oct 13, 2013
flip1995 pushed a commit to flip1995/rust that referenced this pull request Oct 20, 2022
Don't suggest moving tuple structs with a significant drop to late evaluation

fixes rust-lang#9608

changelog: Don't suggest moving tuple structs with a significant drop to late evaluation
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.

5 participants