Skip to content

Change vec::{head,tail,init,last} to return references #5213

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 9 commits into from
236 changes: 167 additions & 69 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,40 +211,41 @@ pub pure fn build_sized_opt<A>(size: Option<uint>,
// Accessors

/// Returns the first element of a vector
pub pure fn head<T:Copy>(v: &[const T]) -> T { v[0] }

/// Returns a vector containing all but the first element of a slice
pub pure fn tail<T:Copy>(v: &[const T]) -> ~[T] {
slice(v, 1u, len(v)).to_vec()
pub pure fn head<T>(v: &r/[T]) -> &r/T {
if v.len() == 0 { fail!(~"head: empty vector") }
&v[0]
}

/**
* Returns a vector containing all but the first `n` \
* elements of a slice
*/
pub pure fn tailn<T:Copy>(v: &[const T], n: uint) -> ~[T] {
slice(v, n, len(v)).to_vec()
/// Returns `Some(x)` where `x` is the first element of the slice `v`,
/// or `None` if the vector is empty.
pub pure fn head_opt<T>(v: &r/[T]) -> Option<&r/T> {
if v.len() == 0 { None } else { Some(&v[0]) }
}

/// Returns a vector containing all but the first element of a slice
pub pure fn tail<T>(v: &r/[T]) -> &r/[T] { slice(v, 1, v.len()) }

/// Returns a vector containing all but the first `n` elements of a slice
pub pure fn tailn<T>(v: &r/[T], n: uint) -> &r/[T] { slice(v, n, v.len()) }

/// Returns a vector containing all but the last element of a slice
pub pure fn init<T:Copy>(v: &[const T]) -> ~[T] {
assert len(v) != 0u;
slice(v, 0u, len(v) - 1u).to_vec()
pub pure fn init<T>(v: &r/[T]) -> &r/[T] { slice(v, 0, v.len() - 1) }

/// Returns a vector containing all but the last `n' elements of a slice
pub pure fn initn<T>(v: &r/[T], n: uint) -> &r/[T] {
slice(v, 0, v.len() - n)
}

/// 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.
Expand Down Expand Up @@ -1692,41 +1693,29 @@ impl<T> Container for &[const T] {
}

pub trait CopyableVector<T> {
pure fn head(&self) -> T;
pure fn init(&self) -> ~[T];
pure fn last(&self) -> T;
pure fn slice(&self, start: uint, end: uint) -> ~[T];
pure fn tail(&self) -> ~[T];
}

/// Extension methods for vectors
impl<T:Copy> CopyableVector<T> for &[const T] {
/// Returns the first element of a vector
#[inline]
pure fn head(&self) -> T { head(*self) }

/// Returns all but the last elemnt of a vector
#[inline]
pure fn init(&self) -> ~[T] { init(*self) }

/// Returns the last element of a `v`, failing if the vector is empty.
#[inline]
pure fn last(&self) -> T { last(*self) }

impl<T: Copy> CopyableVector<T> for &[const T] {
/// Returns a copy of the elements from [`start`..`end`) from `v`.
#[inline]
pure fn slice(&self, start: uint, end: uint) -> ~[T] {
slice(*self, start, end).to_vec()
}

/// Returns all but the first element of a vector
#[inline]
pure fn tail(&self) -> ~[T] { tail(*self) }
}

pub trait ImmutableVector<T> {
pure fn view(&self, start: uint, end: uint) -> &self/[T];
pure fn foldr<U:Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
pure fn head(&self) -> &self/T;
pure fn head_opt(&self) -> Option<&self/T>;
pure fn tail(&self) -> &self/[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];
fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
Expand All @@ -1743,6 +1732,38 @@ impl<T> ImmutableVector<T> for &[T] {
slice(*self, start, end)
}

/// Returns the first element of a vector, failing if the vector is empty.
#[inline]
pure fn head(&self) -> &self/T { head(*self) }

/// Returns the first element of a vector
#[inline]
pure fn head_opt(&self) -> Option<&self/T> { head_opt(*self) }

/// Returns all but the first element of a vector
#[inline]
pure fn tail(&self) -> &self/[T] { tail(*self) }

/// Returns all but the first `n' elements of a vector
#[inline]
pure fn tailn(&self, n: uint) -> &self/[T] { tailn(*self, n) }

/// Returns all but the last elemnt of a vector
#[inline]
pure fn init(&self) -> &self/[T] { init(*self) }

/// Returns all but the last `n' elemnts of a vector
#[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 {
Expand Down Expand Up @@ -2570,27 +2591,117 @@ mod tests {

#[test]
fn test_head() {
let a = ~[11, 12];
assert (head(a) == 11);
let mut a = ~[11];
assert a.head() == &11;
a = ~[11, 12];
assert a.head() == &11;
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_head_empty() {
let a: ~[int] = ~[];
a.head();
}

#[test]
fn test_head_opt() {
let mut a = ~[];
assert a.head_opt() == None;
a = ~[11];
assert a.head_opt().unwrap() == &11;
a = ~[11, 12];
assert a.head_opt().unwrap() == &11;
}

#[test]
fn test_tail() {
let mut a = ~[11];
assert (tail(a) == ~[]);
assert a.tail() == &[];
a = ~[11, 12];
assert a.tail() == &[12];
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_tail_empty() {
let a: ~[int] = ~[];
a.tail();
}

#[test]
fn test_tailn() {
let mut a = ~[11, 12, 13];
assert a.tailn(0) == &[11, 12, 13];
a = ~[11, 12, 13];
assert a.tailn(2) == &[13];
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_tailn_empty() {
let a: ~[int] = ~[];
a.tailn(2);
}

#[test]
fn test_init() {
let mut a = ~[11];
assert a.init() == &[];
a = ~[11, 12];
assert (tail(a) == ~[12]);
assert a.init() == &[11];
}

#[init]
#[should_fail]
#[ignore(cfg(windows))]
fn test_init_empty() {
let a: ~[int] = ~[];
a.init();
}

#[test]
fn test_initn() {
let mut a = ~[11, 12, 13];
assert a.initn(0) == &[11, 12, 13];
a = ~[11, 12, 13];
assert a.initn(2) == &[11];
}

#[init]
#[should_fail]
#[ignore(cfg(windows))]
fn test_initn_empty() {
let a: ~[int] = ~[];
a.initn(2);
}

#[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]
Expand Down Expand Up @@ -3262,12 +3373,6 @@ mod tests {
assert (v2[1] == 10);
}

#[test]
fn test_init() {
let v = init(~[1, 2, 3]);
assert v == ~[1, 2];
}

#[test]
fn test_split() {
fn f(x: &int) -> bool { *x == 3 }
Expand Down Expand Up @@ -3332,13 +3437,6 @@ mod tests {
(~[], ~[1, 2, 3]);
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_init_empty() {
init::<int>(~[]);
}

#[test]
fn test_concat() {
assert concat(~[~[1], ~[2,3]]) == ~[1, 2, 3];
Expand Down
12 changes: 8 additions & 4 deletions src/librust/rust.rc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ fn cmd_help(args: &[~str]) -> ValidUsage {
UsgExec(commandline) => {
let words = str::words(commandline);
let (prog, args) = (words.head(), words.tail());
run::run_program(prog, args);
run::run_program(*prog, args);
}
}
Valid
Expand Down Expand Up @@ -186,7 +186,10 @@ fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
Exec(commandline) => {
let words = str::words(commandline);
let (prog, prog_args) = (words.head(), words.tail());
let exitstatus = run::run_program(prog, prog_args + args);
let exitstatus = run::run_program(
*prog,
vec::append(vec::from_slice(prog_args), args)
);
os::set_exit_status(exitstatus);
Valid
}
Expand Down Expand Up @@ -221,11 +224,12 @@ fn usage() {
}

pub fn main() {
let args = os::args().tail();
let os_args = os::args();
let args = os_args.tail();

if !args.is_empty() {
for commands.each |command| {
if command.cmd == args.head() {
if command.cmd == *args.head() {
let result = do_command(command, args.tail());
if result.is_valid() { return; }
}
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct cache_entry {
metas: @~[@ast::meta_item]
}

fn dump_crates(+crate_cache: @mut ~[cache_entry]) {
fn dump_crates(crate_cache: @mut ~[cache_entry]) {
debug!("resolved crates:");
for crate_cache.each |entry| {
debug!("cnum: %?", entry.cnum);
Expand All @@ -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(
Expand Down
8 changes: 5 additions & 3 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,16 +558,18 @@ pub fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt,
-> csearch::found_ast {
debug!("Looking up item: %d", id);
let item_doc = lookup_item(id, cdata.data);
let path = vec::init(item_path(intr, item_doc));
let path = {
let item_path = item_path(intr, item_doc);
vec::from_slice(item_path.init())
};
match decode_inlined_item(cdata, tcx, path, item_doc) {
Some(ref ii) => csearch::found((/*bad*/copy *ii)),
None => {
match item_parent_item(item_doc) {
Some(did) => {
let did = translate_def_id(cdata, did);
let parent_item = lookup_item(did.node, cdata.data);
match decode_inlined_item(cdata, tcx, path,
parent_item) {
match decode_inlined_item(cdata, tcx, path, parent_item) {
Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)),
None => csearch::not_found
}
Expand Down
Loading