core: convert vec::{last,last_opt} to return references

This commit is contained in:
Erick Tryzelaar 2013-03-05 19:39:18 -08:00
parent a18bf8c67d
commit 743cfce703
15 changed files with 74 additions and 51 deletions

View File

@ -212,7 +212,7 @@ pub pure fn build_sized_opt<A>(size: Option<uint>,
/// Returns the first element of a vector
pub pure fn head<T>(v: &r/[T]) -> &r/T {
if v.len() == 0 { fail!(~"last_unsafe: empty vector") }
if v.len() == 0 { fail!(~"head: empty vector") }
&v[0]
}
@ -237,18 +237,15 @@ pub pure fn initn<T>(v: &r/[T], n: uint) -> &r/[T] {
}
/// Returns the last element of the slice `v`, failing if the slice is empty.
pub pure fn last<T:Copy>(v: &[const T]) -> T {
if len(v) == 0u { fail!(~"last_unsafe: empty vector") }
v[len(v) - 1u]
pub pure fn last<T>(v: &r/[T]) -> &r/T {
if v.len() == 0 { fail!(~"last: empty vector") }
&v[v.len() - 1]
}
/**
* Returns `Some(x)` where `x` is the last element of the slice `v`,
* or `none` if the vector is empty.
*/
pub pure fn last_opt<T:Copy>(v: &[const T]) -> Option<T> {
if len(v) == 0u { return None; }
Some(v[len(v) - 1u])
/// Returns `Some(x)` where `x` is the last element of the slice `v`, or
/// `None` if the vector is empty.
pub pure fn last_opt<T>(v: &r/[T]) -> Option<&r/T> {
if v.len() == 0 { None } else { Some(&v[v.len() - 1]) }
}
/// Return a slice that points into another slice.
@ -1696,16 +1693,11 @@ impl<T> Container for &[const T] {
}
pub trait CopyableVector<T> {
pure fn last(&self) -> T;
pure fn slice(&self, start: uint, end: uint) -> ~[T];
}
/// Extension methods for vectors
impl<T: Copy> CopyableVector<T> for &[const T] {
/// Returns the last element of a `v`, failing if the vector is empty.
#[inline]
pure fn last(&self) -> T { last(*self) }
/// Returns a copy of the elements from [`start`..`end`) from `v`.
#[inline]
pure fn slice(&self, start: uint, end: uint) -> ~[T] {
@ -1721,6 +1713,8 @@ pub trait ImmutableVector<T> {
pure fn tailn(&self, n: uint) -> &self/[T];
pure fn init(&self) -> &self/[T];
pure fn initn(&self, n: uint) -> &self/[T];
pure fn last(&self) -> &self/T;
pure fn last_opt(&self) -> Option<&self/T>;
pure fn foldr<U: Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
pure fn map<U>(&self, f: fn(t: &T) -> U) -> ~[U];
pure fn mapi<U>(&self, f: fn(uint, t: &T) -> U) -> ~[U];
@ -1762,6 +1756,14 @@ impl<T> ImmutableVector<T> for &[T] {
#[inline]
pure fn initn(&self, n: uint) -> &self/[T] { initn(*self, n) }
/// Returns the last element of a `v`, failing if the vector is empty.
#[inline]
pure fn last(&self) -> &self/T { last(*self) }
/// Returns the last element of a `v`, failing if the vector is empty.
#[inline]
pure fn last_opt(&self) -> Option<&self/T> { last_opt(*self) }
/// Reduce a vector from right to left
#[inline]
pure fn foldr<U:Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U {
@ -2679,12 +2681,27 @@ mod tests {
#[test]
fn test_last() {
let mut n = last_opt(~[]);
assert (n.is_none());
n = last_opt(~[1, 2, 3]);
assert (n == Some(3));
n = last_opt(~[1, 2, 3, 4, 5]);
assert (n == Some(5));
let mut a = ~[11];
assert a.last() == &11;
a = ~[11, 12];
assert a.last() == &12;
}
#[test]
#[should_fail]
fn test_last_empty() {
let a: ~[int] = ~[];
a.last();
}
#[test]
fn test_last_opt() {
let mut a = ~[];
assert a.last_opt() == None;
a = ~[11];
assert a.last_opt().unwrap() == &11;
a = ~[11, 12];
assert a.last_opt().unwrap() == &12;
}
#[test]

View File

@ -81,7 +81,9 @@ fn warn_if_multiple_versions(e: @mut Env,
if crate_cache.len() != 0u {
let name = loader::crate_name_from_metas(
/*bad*/copy *crate_cache.last().metas);
*crate_cache[crate_cache.len() - 1].metas
);
let (matches, non_matches) =
partition(crate_cache.map_to_vec(|&entry| {
let othername = loader::crate_name_from_metas(

View File

@ -143,9 +143,9 @@ fn find_library_crate_aux(
pub fn crate_name_from_metas(metas: &[@ast::meta_item]) -> @~str {
let name_items = attr::find_meta_items_by_name(metas, ~"name");
match vec::last_opt(name_items) {
match name_items.last_opt() {
Some(i) => {
match attr::get_meta_item_value_str(i) {
match attr::get_meta_item_value_str(*i) {
Some(n) => n,
// FIXME (#2406): Probably want a warning here since the user
// is using the wrong type of meta item.

View File

@ -1438,7 +1438,7 @@ pub impl Resolver {
type_value_ns => AnyNS
};
let source_ident = full_path.idents.last();
let source_ident = *full_path.idents.last();
let subclass = @SingleImport(binding,
source_ident,
ns);
@ -4087,7 +4087,7 @@ pub impl Resolver {
// First, check to see whether the name is a primitive type.
if path.idents.len() == 1 {
let name = path.idents.last();
let name = *path.idents.last();
match self.primitive_type_table
.primitive_types
@ -4110,7 +4110,7 @@ pub impl Resolver {
debug!("(resolving type) resolved `%s` to \
type %?",
*self.session.str_of(
path.idents.last()),
*path.idents.last()),
def);
result_def = Some(def);
}
@ -4296,7 +4296,7 @@ pub impl Resolver {
path.span,
fmt!("not an enum variant: %s",
*self.session.str_of(
path.idents.last())));
*path.idents.last())));
}
None => {
self.session.span_err(path.span,
@ -4418,7 +4418,7 @@ pub impl Resolver {
namespace);
}
return self.resolve_identifier(path.idents.last(),
return self.resolve_identifier(*path.idents.last(),
namespace,
check_ribs,
path.span);
@ -4552,7 +4552,7 @@ pub impl Resolver {
}
}
let name = path.idents.last();
let name = *path.idents.last();
match self.resolve_definition_of_name_in_module(containing_module,
name,
namespace,
@ -4601,7 +4601,7 @@ pub impl Resolver {
}
}
let name = path.idents.last();
let name = *path.idents.last();
match self.resolve_definition_of_name_in_module(containing_module,
name,
namespace,

View File

@ -2207,7 +2207,7 @@ pub fn register_fn_fuller(ccx: @CrateContext,
ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
let ps = if attr::attrs_contains_name(attrs, "no_mangle") {
path_elt_to_str(path.last(), ccx.sess.parse_sess.interner)
path_elt_to_str(*path.last(), ccx.sess.parse_sess.interner)
} else {
mangle_exported_name(ccx, /*bad*/copy path, node_type)
};

View File

@ -792,12 +792,14 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
match arg.pat.node {
ast::pat_ident(_, path, _) => {
// XXX: This is wrong; it should work for multiple bindings.
let mdnode = create_var(tg,
context.node,
*cx.sess.str_of(path.idents.last()),
filemd.node,
loc.line as int,
tymd.node);
let mdnode = create_var(
tg,
context.node,
*cx.sess.str_of(*path.idents.last()),
filemd.node,
loc.line as int,
tymd.node
);
let mdval = @Metadata {
node: mdnode,

View File

@ -57,7 +57,7 @@ pub fn parse_name(id: ~str) -> result::Result<~str, ~str> {
}
}
result::Ok(parts.last())
result::Ok(copy *parts.last())
}
struct ListenerFn {
@ -516,9 +516,11 @@ pub fn get_pkg(id: ~str,
return result::Err(~"package not found");
}
result::Ok(sort::merge_sort(possibs, |v1, v2| {
let possibs = sort::merge_sort(possibs, |v1, v2| {
v1.vers <= v2.vers
}).last())
});
result::Ok(copy *possibs.last())
}
pub fn add_pkg(pkg: &Package) -> bool {

View File

@ -346,7 +346,7 @@ pub impl BigUint {
}
let mut shift = 0;
let mut n = other.data.last();
let mut n = *other.data.last();
while n < (1 << BigDigit::bits - 2) {
n <<= 1;
shift += 1;
@ -384,7 +384,7 @@ pub impl BigUint {
}
let an = vec::slice(a.data, a.data.len() - n, a.data.len());
let bn = b.data.last();
let bn = *b.data.last();
let mut d = ~[];
let mut carry = 0;
for vec::rev_each(an) |elt| {

View File

@ -759,7 +759,7 @@ pub fn Decoder(json: Json) -> Decoder {
priv impl Decoder {
fn peek(&self) -> &self/Json {
if self.stack.len() == 0 { self.stack.push(&self.json); }
vec::last(self.stack)
self.stack[self.stack.len() - 1]
}
fn pop(&self) -> &self/Json {

View File

@ -197,7 +197,7 @@ mod tests {
let mut sorted = merge_sort(data, le);
let mut heap = from_vec(data);
while !heap.is_empty() {
assert *heap.top() == sorted.last();
assert heap.top() == sorted.last();
assert heap.pop() == sorted.pop();
}
}

View File

@ -31,7 +31,7 @@ pub pure fn path_name_i(idents: &[ident], intr: @token::ident_interner)
}
pub pure fn path_to_ident(p: @path) -> ident { vec::last(p.idents) }
pub pure fn path_to_ident(p: @path) -> ident { copy *p.idents.last() }
pub pure fn local_def(id: node_id) -> def_id {
ast::def_id { crate: local_crate, node: id }

View File

@ -229,7 +229,7 @@ fn last_meta_item_by_name(items: &[@ast::meta_item], name: &str)
-> Option<@ast::meta_item> {
let items = attr::find_meta_items_by_name(items, name);
vec::last_opt(items)
items.last_opt().map(|item| **item)
}
pub fn last_meta_item_value_str_by_name(items: &[@ast::meta_item], name: &str)

View File

@ -167,7 +167,7 @@ pub fn tt_next_token(r: @mut TtReader) -> TokenAndSpan {
while r.cur.idx >= r.cur.readme.len() {
/* done with this set; pop or repeat? */
if ! r.cur.dotdotdoted
|| r.repeat_idx.last() == r.repeat_len.last() - 1 {
|| { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } {
match r.cur.up {
None => {

View File

@ -93,7 +93,7 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
fn_box: || @Cons((), fn_box()),
tuple: (@Cons((), st.tuple.first()),
~Cons((), @*st.tuple.second())),
vec: st.vec + ~[@Cons((), st.vec.last())],
vec: st.vec + ~[@Cons((), *st.vec.last())],
res: r(@Cons((), st.res._l))
}
}

View File

@ -35,5 +35,5 @@ pub fn main() {
let ps = vec::zip(chars, ints);
assert (ps.head() == &('a', 1u));
assert (ps.last() == (j as char, 10u));
assert (ps.last() == &(j as char, 10u));
}