stdlib: Make list::find do what the docs say it does.

Talked on #rust about this change, got approval from graydon and brson. Will bring up tomorrow at meeting to verify.
This commit is contained in:
Patrick Walton 2012-03-12 18:26:31 -07:00
parent 3de30f4ef2
commit 4571175568
2 changed files with 25 additions and 9 deletions

View File

@ -40,13 +40,13 @@ Apply function `f` to each element of `v`, starting from the first.
When function `f` returns true then an option containing the element
is returned. If `f` matches no elements then none is returned.
"]
fn find<T: copy, U: copy>(ls: list<T>, f: fn(T) -> option<U>)
-> option<U> {
fn find<T: copy>(ls: list<T>, f: fn(T) -> bool) -> option<T> {
let ls = ls;
loop {
alt ls {
cons(hd, tl) {
alt f(hd) { none { ls = *tl; } some(rs) { ret some(rs); } }
if f(hd) { ret some(hd); }
ls = *tl;
}
nil { ret none; }
}
@ -195,16 +195,14 @@ mod tests {
#[test]
fn test_find_success() {
fn match(&&i: int) -> option<int> {
ret if i == 2 { option::some(i) } else { option::none::<int> };
}
fn match(&&i: int) -> bool { ret i == 2; }
let l = from_vec([0, 1, 2]);
assert (list::find(l, match) == option::some(2));
}
#[test]
fn test_find_fail() {
fn match(&&_i: int) -> option<int> { ret option::none::<int>; }
fn match(&&_i: int) -> bool { ret false; }
let l = from_vec([0, 1, 2]);
let empty = list::nil::<int>;
assert (list::find(l, match) == option::none::<int>);

View File

@ -1469,6 +1469,24 @@ fn is_exported(e: env, i: ident, m: @indexed_mod) -> bool {
|| e.resolve_unexported;
}
// A list search function. Applies `f` to each element of `v`, starting from
// the first. When `f` returns `some(x)`, `list_search` returns `some(x)`. If
// `f` returns `none` for every element, `list_search` returns `none`.
fn list_search<T: copy, U: copy>(ls: list<T>, f: fn(T) -> option<U>)
-> option<U> {
let ls = ls;
loop {
alt ls {
cons(hd, tl) {
let result = f(hd);
if !is_none(result) { ret result; }
ls = *tl;
}
nil { ret none; }
}
};
}
fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
ns: namespace, dr: dir) -> option<def> {
let info = e.mod_map.get(node_id);
@ -1479,7 +1497,7 @@ fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident,
alt info.index.find(id) {
none { }
some(lst) {
let found = list::find(lst, bind lookup_in_mie(e, _, ns));
let found = list_search(lst, bind lookup_in_mie(e, _, ns));
if !is_none(found) {
ret found;
}
@ -2072,7 +2090,7 @@ fn check_exports(e: @env) {
e.sess.span_fatal(sp, #fmt("undefined id %s in an export", id));
}
some(ms) {
let maybe_id = list::find(ms) {|m|
let maybe_id = list_search(ms) {|m|
alt m {
mie_item(@{node: item_enum(_, _), id, _}) { some(id) }
_ { none }