Rename last to last_opt, last_unsafe to last

As per discussion on IRC. I am about to file an RFC for further
discussion about the more general issue of whether to enforce
invariants through types, typestate, or dynamic checks, but for now,
removing the misleading name "last_unsafe".
This commit is contained in:
Tim Chevalier 2012-03-08 15:24:27 -08:00
parent 8047c0cd68
commit 0c5fdc8745
13 changed files with 30 additions and 31 deletions

View file

@ -170,7 +170,7 @@ fn splitext(p: path) -> (str, str) {
if vec::len(parts) > 1u { if vec::len(parts) > 1u {
let base = str::connect(vec::init(parts), "."); let base = str::connect(vec::init(parts), ".");
// We just checked that parts is non-empty, so this is safe // We just checked that parts is non-empty, so this is safe
let ext = "." + vec::last_unsafe(parts); let ext = "." + vec::last(parts);
fn is_dotfile(base: str) -> bool { fn is_dotfile(base: str) -> bool {
str::is_empty(base) str::is_empty(base)

View file

@ -187,29 +187,26 @@ fn init<T: copy>(v: [const T]) -> [T] {
/* /*
Function: last Function: last
Returns the last element of a vector
Returns:
An option containing the last element of `v` if `v` is not empty, or
none if `v` is empty.
*/
pure fn last<T: copy>(v: [const T]) -> option<T> {
if len(v) == 0u { ret none; }
ret some(v[len(v) - 1u]);
}
/*
Function: last_unsafe
Returns the last element of a `v`, failing if the vector is empty. Returns the last element of a `v`, failing if the vector is empty.
*/ */
pure fn last_unsafe<T: copy>(v: [const T]) -> T { pure fn last<T: copy>(v: [const T]) -> T {
if len(v) == 0u { fail "last_unsafe: empty vector" } if len(v) == 0u { fail "last_unsafe: empty vector" }
v[len(v) - 1u] v[len(v) - 1u]
} }
/*
Function: last_opt
Returns some(x) where `x` is the last element of a vector `v`,
or none if the vector is empty.
*/
pure fn last_opt<T: copy>(v: [const T]) -> option<T> {
if len(v) == 0u { ret none; }
some(v[len(v) - 1u])
}
/* /*
Function: slice Function: slice
@ -1270,11 +1267,11 @@ mod tests {
#[test] #[test]
fn test_last() { fn test_last() {
let n = last([]); let n = last_opt([]);
assert (n == none); assert (n == none);
n = last([1, 2, 3]); n = last_opt([1, 2, 3]);
assert (n == some(3)); assert (n == some(3));
n = last([1, 2, 3, 4, 5]); n = last_opt([1, 2, 3, 4, 5]);
assert (n == some(5)); assert (n == some(5));
} }

View file

@ -271,7 +271,7 @@ fn splitext(p: path) -> (str, str) {
if vec::len(parts) > 1u { if vec::len(parts) > 1u {
let base = str::connect(vec::init(parts), "."); let base = str::connect(vec::init(parts), ".");
// We just checked that parts is non-empty // We just checked that parts is non-empty
let ext = "." + vec::last_unsafe(parts); let ext = "." + vec::last(parts);
fn is_dotfile(base: str) -> bool { fn is_dotfile(base: str) -> bool {
str::is_empty(base) str::is_empty(base)

View file

@ -256,7 +256,7 @@ fn meta_item_from_list(
name: str name: str
) -> option<@ast::meta_item> { ) -> option<@ast::meta_item> {
let items = attr::find_meta_items_by_name(items, name); let items = attr::find_meta_items_by_name(items, name);
vec::last(items) vec::last_opt(items)
} }
fn meta_item_value_from_list( fn meta_item_value_from_list(

View file

@ -144,7 +144,7 @@ fn find_library_crate(sess: session::session, ident: ast::ident,
let crate_name = let crate_name =
{ {
let name_items = attr::find_meta_items_by_name(metas, "name"); let name_items = attr::find_meta_items_by_name(metas, "name");
alt vec::last(name_items) { alt vec::last_opt(name_items) {
some(i) { some(i) {
alt attr::get_meta_item_value_str(i) { alt attr::get_meta_item_value_str(i) {
some(n) { n } some(n) { n }

View file

@ -189,7 +189,7 @@ fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
view_path_glob(pth, id) | view_path_list(pth, _, id) { view_path_glob(pth, id) | view_path_list(pth, _, id) {
// should be a constraint on the type // should be a constraint on the type
assert (vec::is_not_empty(*pth)); assert (vec::is_not_empty(*pth));
(id, vec::last_unsafe(*pth)) (id, vec::last(*pth))
} }
}; };
cx.map.insert(id, node_export(vp, extend(cx, name))); cx.map.insert(id, node_export(vp, extend(cx, name)));

View file

@ -70,5 +70,5 @@ fn pat_binding_ids(dm: resolve::def_map, pat: @pat) -> [node_id] {
fn path_to_ident(p: @path) -> ident { fn path_to_ident(p: @path) -> ident {
assert (vec::is_not_empty(p.node.idents)); // should be a constraint on path assert (vec::is_not_empty(p.node.idents)); // should be a constraint on path
vec::last_unsafe(p.node.idents) vec::last(p.node.idents)
} }

View file

@ -183,7 +183,7 @@ fn kill_poststate(fcx: fn_ctxt, id: node_id, c: tsconstr) -> bool {
fn clear_in_poststate_expr(fcx: fn_ctxt, e: @expr, t: poststate) { fn clear_in_poststate_expr(fcx: fn_ctxt, e: @expr, t: poststate) {
alt e.node { alt e.node {
expr_path(p) { expr_path(p) {
alt vec::last(p.node.idents) { alt vec::last_opt(p.node.idents) {
some(i) { some(i) {
alt local_node_id_to_def(fcx, e.id) { alt local_node_id_to_def(fcx, e.id) {
some(def_local(nid, _)) { some(def_local(nid, _)) {

View file

@ -406,7 +406,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
init_assign), init_assign),
exs, return_val); exs, return_val);
let base_pres = alt vec::last(exs) { none { pres } let base_pres = alt vec::last_opt(exs) { none { pres }
some(f) { expr_poststate(fcx.ccx, f) }}; some(f) { expr_poststate(fcx.ccx, f) }};
option::may(maybe_base, {|base| option::may(maybe_base, {|base|
changed |= find_pre_post_state_expr(fcx, base_pres, base) | changed |= find_pre_post_state_expr(fcx, base_pres, base) |

View file

@ -2642,7 +2642,7 @@ fn bind_params(fcx: @fn_ctxt, tp: ty::t, count: uint)
} }
fn get_self_info(ccx: @crate_ctxt) -> option<self_info> { fn get_self_info(ccx: @crate_ctxt) -> option<self_info> {
ret vec::last(ccx.self_infos); ret vec::last_opt(ccx.self_infos);
} }
fn check_decl_initializer(fcx: @fn_ctxt, nid: ast::node_id, fn check_decl_initializer(fcx: @fn_ctxt, nid: ast::node_id,

View file

@ -89,7 +89,9 @@ fn local_rhs_span(l: @ast::local, def: span) -> span {
} }
fn is_main_name(path: middle::ast_map::path) -> bool { fn is_main_name(path: middle::ast_map::path) -> bool {
option::get(vec::last(path)) == middle::ast_map::path_name("main") // FIXME: path should be a constrained type, so we know
// the call to last doesn't fail
vec::last(path) == middle::ast_map::path_name("main")
} }
// //

View file

@ -163,7 +163,7 @@ fn build_reexport_path_map(srv: astsrv::srv, -def_map: def_map) -> path_map {
}; };
// should be a constraint on the node_export constructor // should be a constraint on the node_export constructor
// that guarantees path is non-empty // that guarantees path is non-empty
let name = alt check vec::last_unsafe(*path) { let name = alt check vec::last(*path) {
ast_map::path_name(nm) { nm } ast_map::path_name(nm) { nm }
}; };
let modpath = ast_map::path_to_str(vec::init(*path)); let modpath = ast_map::path_to_str(vec::init(*path));

View file

@ -19,5 +19,5 @@ fn main() {
check (is_not_empty(ps)); check (is_not_empty(ps));
assert (head(ps) == ('a', 1u)); assert (head(ps) == ('a', 1u));
assert (last_unsafe(ps) == (j as char, 10u)); assert (last(ps) == (j as char, 10u));
} }