From 259636a112804b94530c409a468b97d4366bb0d3 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 26 Jan 2012 08:39:45 -0800 Subject: [PATCH 1/6] core: rename vec::position* functions Almost all of the vec functions that predicates don't have a corresponding function that takes a single element, so this commit renames the common fn usecase to be the default. --- doc/tutorial.md | 4 ++-- src/comp/middle/alias.rs | 2 +- src/comp/middle/shape.rs | 2 +- src/comp/middle/trans/base.rs | 2 +- src/comp/middle/typeck.rs | 2 +- src/libcore/vec.rs | 37 +++++++++++++++++++---------------- src/libstd/getopts.rs | 2 +- 7 files changed, 27 insertions(+), 24 deletions(-) diff --git a/doc/tutorial.md b/doc/tutorial.md index 9a955f8a8b83..29862e7ba5b6 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -929,8 +929,8 @@ for the parameter list, as in `{|| ...}`. Partial application is done using the `bind` keyword in Rust. ~~~~ -let daynum = bind vec::position(_, ["mo", "tu", "we", "do", - "fr", "sa", "su"]); +let daynum = bind vec::position_elt(["mo", "tu", "we", "do", + "fr", "sa", "su"], _); ~~~~ Binding a function produces a boxed closure (`fn@` type) in which some diff --git a/src/comp/middle/alias.rs b/src/comp/middle/alias.rs index 10a45349d4a9..a8a88dfa193e 100644 --- a/src/comp/middle/alias.rs +++ b/src/comp/middle/alias.rs @@ -679,7 +679,7 @@ fn filter_invalid(src: list<@invalid>, bs: [binding]) -> list<@invalid> { while cur != list::nil { alt cur { list::cons(head, tail) { - let p = vec::position_pred(bs, {|b| b.node_id == head.node_id}); + let p = vec::position(bs, {|b| b.node_id == head.node_id}); if !is_none(p) { out = list::cons(head, @out); } cur = *tail; } diff --git a/src/comp/middle/shape.rs b/src/comp/middle/shape.rs index 7612148df453..389f490e8e9c 100644 --- a/src/comp/middle/shape.rs +++ b/src/comp/middle/shape.rs @@ -430,7 +430,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { } ty::ty_param(n, _) { // Find the type parameter in the parameter list. - alt vec::position(n, ty_param_map) { + alt vec::position_elt(ty_param_map, n) { some(i) { s += [shape_var, i as u8]; } none { fail "ty param not found in ty_param_map"; } } diff --git a/src/comp/middle/trans/base.rs b/src/comp/middle/trans/base.rs index 9b423be389e4..03c98dfa827d 100644 --- a/src/comp/middle/trans/base.rs +++ b/src/comp/middle/trans/base.rs @@ -3375,7 +3375,7 @@ fn trans_rec(bcx: @block_ctxt, fields: [ast::field], let ty_fields = alt ty::struct(bcx_tcx(bcx), t) { ty::ty_rec(f) { f } }; let temp_cleanups = []; for fld in fields { - let ix = option::get(vec::position_pred(ty_fields, {|ft| + let ix = option::get(vec::position(ty_fields, {|ft| str::eq(fld.node.ident, ft.ident) })); let dst = GEP_tup_like_1(bcx, t, addr, [0, ix as int]); diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 8a06314a96bc..b91379246520 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -1513,7 +1513,7 @@ fn lookup_method(fcx: @fn_ctxt, isc: resolve::iscopes, ty::ty_iface(i, tps) { (i, tps) } }; let ifce_methods = ty::iface_methods(tcx, iid); - alt vec::position_pred(*ifce_methods, {|m| m.ident == name}) { + alt vec::position(*ifce_methods, {|m| m.ident == name}) { some(pos) { let m = ifce_methods[pos]; ret some({method_ty: ty::mk_fn(tcx, m.fty), diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 4dabab99c238..1279d1a8e400 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -614,7 +614,7 @@ fn find(v: [T], f: fn(T) -> bool) -> option::t { } /* -Function: position +Function: position_elt Find the first index containing a matching value @@ -623,18 +623,16 @@ Returns: option::some(uint) - The first index containing a matching value option::none - No elements matched */ -fn position(x: T, v: [T]) -> option::t { - let i: uint = 0u; - while i < len(v) { if x == v[i] { ret some::(i); } i += 1u; } - ret none; +fn position_elt(v: [T], x: T) -> option::t { + position(v) { |y| x == y } } /* -Function: position_pred +Function: position Find the first index for which the value matches some predicate */ -fn position_pred(v: [T], f: fn(T) -> bool) -> option::t { +fn position(v: [T], f: fn(T) -> bool) -> option::t { let i: uint = 0u; while i < len(v) { if f(v[i]) { ret some::(i); } i += 1u; } ret none; @@ -1453,21 +1451,26 @@ mod tests { } #[test] - fn test_position() { - let v1: [int] = [1, 2, 3, 3, 2, 5]; - assert (position(1, v1) == option::some::(0u)); - assert (position(2, v1) == option::some::(1u)); - assert (position(5, v1) == option::some::(5u)); - assert (position(4, v1) == option::none::); + fn test_position_elt() { + assert position_elt([], 1) == none; + + let v1 = [1, 2, 3, 3, 2, 5]; + assert position_elt(v1, 1) == some(0u); + assert position_elt(v1, 2) == some(1u); + assert position_elt(v1, 5) == some(5u); + assert position_elt(v1, 4) == none; } #[test] - fn test_position_pred() { + fn test_position() { fn less_than_three(&&i: int) -> bool { ret i < 3; } fn is_eighteen(&&i: int) -> bool { ret i == 18; } - let v1: [int] = [5, 4, 3, 2, 1]; - assert position_pred(v1, less_than_three) == option::some::(3u); - assert position_pred(v1, is_eighteen) == option::none::; + + assert position([], less_than_three) == none; + + let v1 = [5, 4, 3, 2, 1]; + assert position(v1, less_than_three) == some(3u); + assert position(v1, is_eighteen) == none; } #[test] diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs index b870dde34c6e..c517a2f996df 100644 --- a/src/libstd/getopts.rs +++ b/src/libstd/getopts.rs @@ -149,7 +149,7 @@ fn name_str(nm: name) -> str { } fn find_opt(opts: [opt], nm: name) -> option::t { - vec::position_pred(opts, { |opt| opt.name == nm }) + vec::position(opts, { |opt| opt.name == nm }) } /* From 1be3a7c2637b11f82bcbbbff5e92532d7e2fc9b8 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 26 Jan 2012 08:42:50 -0800 Subject: [PATCH 2/6] core: add (,r)position(,_from) functions This is to help search through a vector better. --- src/libcore/vec.rs | 140 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 1279d1a8e400..78274e2ae379 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -630,11 +630,79 @@ fn position_elt(v: [T], x: T) -> option::t { /* Function: position -Find the first index for which the value matches some predicate +Find the first index matching some predicate + +Apply function `f` to each element of `v`. When function `f` returns true +then an option containing the index is returned. If `f` matches no elements +then none is returned. */ fn position(v: [T], f: fn(T) -> bool) -> option::t { - let i: uint = 0u; - while i < len(v) { if f(v[i]) { ret some::(i); } i += 1u; } + position_from(v, 0u, len(v), f) +} + +/* +Function: position_from + +Find the first index matching some predicate within a range + +Apply function `f` to each element of `v` between the range [`start`, `end`). +When function `f` returns true then an option containing the index is +returned. If `f` matches no elements then none is returned. +*/ +fn position_from(v: [T], start: uint, end: uint, f: fn(T) -> bool) -> + option::t { + assert start <= end; + assert end <= len(v); + let i = start; + while i < end { if f(v[i]) { ret some::(i); } i += 1u; } + ret none; +} + +/* +Function: rposition_elt + +Find the last index containing a matching value + +Returns: + +option::some(uint) - The last index containing a matching value +option::none - No elements matched +*/ +fn rposition_elt(v: [T], x: T) -> option::t { + rposition(v) { |y| x == y } +} + +/* +Function: rposition + +Find the last index matching some predicate + +Apply function `f` to each element of `v` in reverse order. When function +`f` returns true then an option containing the index is returned. If `f` +matches no elements then none is returned. +*/ +fn rposition(v: [T], f: fn(T) -> bool) -> option::t { + rposition_from(v, 0u, len(v), f) +} + +/* +Function: rposition_from + +Find the last index matching some predicate within a range + +Apply function `f` to each element of `v` in reverse order between the range +[`start`, `end`). When function `f` returns true then an option containing +the index is returned. If `f` matches no elements then none is returned. +*/ +fn rposition_from(v: [T], start: uint, end: uint, f: fn(T) -> bool) -> + option::t { + assert start <= end; + assert end <= len(v); + let i = end; + while i > start { + if f(v[i - 1u]) { ret some::(i - 1u); } + i -= 1u; + } ret none; } @@ -1474,6 +1542,72 @@ mod tests { } #[test] + fn test_position_from() { + assert position_from([], 0u, 0u, f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert position_from(v, 0u, 0u, f) == none; + assert position_from(v, 0u, 1u, f) == none; + assert position_from(v, 0u, 2u, f) == some(1u); + assert position_from(v, 0u, 3u, f) == some(1u); + assert position_from(v, 0u, 4u, f) == some(1u); + + assert position_from(v, 1u, 1u, f) == none; + assert position_from(v, 1u, 2u, f) == some(1u); + assert position_from(v, 1u, 3u, f) == some(1u); + assert position_from(v, 1u, 4u, f) == some(1u); + + assert position_from(v, 2u, 2u, f) == none; + assert position_from(v, 2u, 3u, f) == none; + assert position_from(v, 2u, 4u, f) == some(3u); + + assert position_from(v, 3u, 3u, f) == none; + assert position_from(v, 3u, 4u, f) == some(3u); + + assert position_from(v, 4u, 4u, f) == none; + } + + #[test] + fn test_rposition() { + assert find([], f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + fn g(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'd' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert position(v, f) == some(1u); + assert position(v, g) == none; + } + + #[test] + fn test_rposition_from() { + assert rposition_from([], 0u, 0u, f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert rposition_from(v, 0u, 0u, f) == none; + assert rposition_from(v, 0u, 1u, f) == none; + assert rposition_from(v, 0u, 2u, f) == some(1u); + assert rposition_from(v, 0u, 3u, f) == some(1u); + assert rposition_from(v, 0u, 4u, f) == some(3u); + + assert rposition_from(v, 1u, 1u, f) == none; + assert rposition_from(v, 1u, 2u, f) == some(1u); + assert rposition_from(v, 1u, 3u, f) == some(1u); + assert rposition_from(v, 1u, 4u, f) == some(3u); + + assert rposition_from(v, 2u, 2u, f) == none; + assert rposition_from(v, 2u, 3u, f) == none; + assert rposition_from(v, 2u, 4u, f) == some(3u); + + assert rposition_from(v, 3u, 3u, f) == none; + assert rposition_from(v, 3u, 4u, f) == some(3u); + + assert rposition_from(v, 4u, 4u, f) == none; + } fn reverse_and_reversed() { let v: [mutable int] = [mutable 10, 20]; assert (v[0] == 10); From 025e6ff1586999caef7460a1884cbd9685ad2277 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 26 Jan 2012 18:13:43 -0800 Subject: [PATCH 3/6] core: add vec spliting functions. --- src/libcore/vec.rs | 146 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 78274e2ae379..9a0970fae4e5 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -278,6 +278,110 @@ fn slice_mut(v: [const T], start: uint, end: uint) -> [mutable T] { ret result; } +/* +Function: split + +Split the vector `v` by applying each element against the predicate `f`. +*/ +fn split(v: [T], f: fn(T) -> bool) -> [[T]] { + let ln = len(v); + if (ln == 0u) { ret [] } + + let start = 0u; + let result = []; + while start < ln { + alt position_from(v, start, ln, f) { + none { break } + some(i) { + push(result, slice(v, start, i)); + start = i + 1u; + } + } + } + push(result, slice(v, start, ln)); + result +} + +/* +Function: splitn + +Split the vector `v` by applying each element against the predicate `f` up +to `n` times. +*/ +fn splitn(v: [T], n: uint, f: fn(T) -> bool) -> [[T]] { + let ln = len(v); + if (ln == 0u) { ret [] } + + let start = 0u; + let count = n; + let result = []; + while start < ln && count > 0u { + alt position_from(v, start, ln, f) { + none { break } + some(i) { + push(result, slice(v, start, i)); + // Make sure to skip the separator. + start = i + 1u; + count -= 1u; + } + } + } + push(result, slice(v, start, ln)); + result +} + +/* +Function: rsplit + +Reverse split the vector `v` by applying each element against the predicate +`f`. +*/ +fn rsplit(v: [T], f: fn(T) -> bool) -> [[T]] { + let ln = len(v); + if (ln == 0u) { ret [] } + + let end = ln; + let result = []; + while end > 0u { + alt rposition_from(v, 0u, end, f) { + none { break } + some(i) { + push(result, slice(v, i + 1u, end)); + end = i; + } + } + } + push(result, slice(v, 0u, end)); + reversed(result) +} + +/* +Function: rsplitn + +Reverse split the vector `v` by applying each element against the predicate +`f` up to `n times. +*/ +fn rsplitn(v: [T], n: uint, f: fn(T) -> bool) -> [[T]] { + let ln = len(v); + if (ln == 0u) { ret [] } + + let end = ln; + let count = n; + let result = []; + while end > 0u && count > 0u { + alt rposition_from(v, 0u, end, f) { + none { break } + some(i) { + push(result, slice(v, i + 1u, end)); + // Make sure to skip the separator. + end = i; + count -= 1u; + } + } + } + push(result, slice(v, 0u, end)); + reversed(result) +} // Mutators @@ -1641,6 +1745,48 @@ mod tests { assert v == [1, 2]; } + #[test] + fn test_split() { + fn f(&&x: int) -> bool { x == 3 } + + assert split([], f) == []; + assert split([1, 2], f) == [[1, 2]]; + assert split([3, 1, 2], f) == [[], [1, 2]]; + assert split([1, 2, 3], f) == [[1, 2], []]; + assert split([1, 2, 3, 4, 3, 5], f) == [[1, 2], [4], [5]]; + } + + #[test] + fn test_splitn() { + fn f(&&x: int) -> bool { x == 3 } + + assert splitn([], 1u, f) == []; + assert splitn([1, 2], 1u, f) == [[1, 2]]; + assert splitn([3, 1, 2], 1u, f) == [[], [1, 2]]; + assert splitn([1, 2, 3], 1u, f) == [[1, 2], []]; + assert splitn([1, 2, 3, 4, 3, 5], 1u, f) == [[1, 2], [4, 3, 5]]; + } + + #[test] + fn test_rsplit() { + fn f(&&x: int) -> bool { x == 3 } + + assert rsplit([], f) == []; + assert rsplit([1, 2], f) == [[1, 2]]; + assert rsplit([1, 2, 3], f) == [[1, 2], []]; + assert rsplit([1, 2, 3, 4, 3, 5], f) == [[1, 2], [4], [5]]; + } + + #[test] + fn test_rsplitn() { + fn f(&&x: int) -> bool { x == 3 } + + assert rsplitn([], 1u, f) == []; + assert rsplitn([1, 2], 1u, f) == [[1, 2]]; + assert rsplitn([1, 2, 3], 1u, f) == [[1, 2], []]; + assert rsplitn([1, 2, 3, 4, 3, 5], 1u, f) == [[1, 2, 3, 4], [5]]; + } + #[test] // FIXME: Windows can't undwind #[ignore(cfg(target_os = "win32"))] From f98210db074595c726f8a2913149cb536a893de3 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Thu, 26 Jan 2012 18:14:27 -0800 Subject: [PATCH 4/6] core: Flesh out vec find functions. --- src/libcore/vec.rs | 128 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 125 insertions(+), 3 deletions(-) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 9a0970fae4e5..3e888008c684 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -706,15 +706,55 @@ fn count(x: T, v: [const T]) -> uint { /* Function: find -Search for an element that matches a given predicate +Search for the first element that matches a given predicate 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(v: [T], f: fn(T) -> bool) -> option::t { - for elt: T in v { if f(elt) { ret some(elt); } } - ret none; + find_from(v, 0u, len(v), f) +} + +/* +Function: find_from + +Search for the first element that matches a given predicate within a range + +Apply function `f` to each element of `v` within the range [`start`, `end`). +When function `f` returns true then an option containing the element +is returned. If `f` matches no elements then none is returned. +*/ +fn find_from(v: [T], start: uint, end: uint, f: fn(T) -> bool) -> + option::t { + option::map(position_from(v, start, end, f)) { |i| v[i] } +} + +/* +Function: rfind + +Search for the last element that matches a given predicate + +Apply function `f` to each element of `v` in reverse order. When function `f` +returns true then an option containing the element is returned. If `f` +matches no elements then none is returned. +*/ +fn rfind(v: [T], f: fn(T) -> bool) -> option::t { + rfind_from(v, 0u, len(v), f) +} + +/* +Function: rfind_from + +Search for the last element that matches a given predicate within a range + +Apply function `f` to each element of `v` in reverse order within the range +[`start`, `end`). When function `f` returns true then an option containing +the element is returned. If `f` matches no elements then none is returned. +*/ +fn rfind_from(v: [T], start: uint, end: uint, f: fn(T) -> bool) -> + option::t { + option::map(rposition_from(v, start, end, f)) { |i| v[i] } } /* @@ -1673,6 +1713,46 @@ mod tests { assert position_from(v, 4u, 4u, f) == none; } + #[test] + fn test_find() { + assert find([], f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + fn g(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'd' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert find(v, f) == some((1, 'b')); + assert find(v, g) == none; + } + + #[test] + fn test_find_from() { + assert find_from([], 0u, 0u, f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert find_from(v, 0u, 0u, f) == none; + assert find_from(v, 0u, 1u, f) == none; + assert find_from(v, 0u, 2u, f) == some((1, 'b')); + assert find_from(v, 0u, 3u, f) == some((1, 'b')); + assert find_from(v, 0u, 4u, f) == some((1, 'b')); + + assert find_from(v, 1u, 1u, f) == none; + assert find_from(v, 1u, 2u, f) == some((1, 'b')); + assert find_from(v, 1u, 3u, f) == some((1, 'b')); + assert find_from(v, 1u, 4u, f) == some((1, 'b')); + + assert find_from(v, 2u, 2u, f) == none; + assert find_from(v, 2u, 3u, f) == none; + assert find_from(v, 2u, 4u, f) == some((3, 'b')); + + assert find_from(v, 3u, 3u, f) == none; + assert find_from(v, 3u, 4u, f) == some((3, 'b')); + + assert find_from(v, 4u, 4u, f) == none; + } + #[test] fn test_rposition() { assert find([], f) == none; @@ -1712,6 +1792,48 @@ mod tests { assert rposition_from(v, 4u, 4u, f) == none; } + + #[test] + fn test_rfind() { + assert rfind([], f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + fn g(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'd' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert rfind(v, f) == some((3, 'b')); + assert rfind(v, g) == none; + } + + #[test] + fn test_rfind_from() { + assert rfind_from([], 0u, 0u, f) == none; + + fn f(xy: (int, char)) -> bool { let (_x, y) = xy; y == 'b' } + let v = [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')]; + + assert rfind_from(v, 0u, 0u, f) == none; + assert rfind_from(v, 0u, 1u, f) == none; + assert rfind_from(v, 0u, 2u, f) == some((1, 'b')); + assert rfind_from(v, 0u, 3u, f) == some((1, 'b')); + assert rfind_from(v, 0u, 4u, f) == some((3, 'b')); + + assert rfind_from(v, 1u, 1u, f) == none; + assert rfind_from(v, 1u, 2u, f) == some((1, 'b')); + assert rfind_from(v, 1u, 3u, f) == some((1, 'b')); + assert rfind_from(v, 1u, 4u, f) == some((3, 'b')); + + assert rfind_from(v, 2u, 2u, f) == none; + assert rfind_from(v, 2u, 3u, f) == none; + assert rfind_from(v, 2u, 4u, f) == some((3, 'b')); + + assert rfind_from(v, 3u, 3u, f) == none; + assert rfind_from(v, 3u, 4u, f) == some((3, 'b')); + + assert rfind_from(v, 4u, 4u, f) == none; + } + + #[test] fn reverse_and_reversed() { let v: [mutable int] = [mutable 10, 20]; assert (v[0] == 10); From 5b2c0a999fd9d0a92c82f2615a00cd13ced7a077 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 27 Jan 2012 20:39:16 -0800 Subject: [PATCH 5/6] std: Whitespace cleanup. --- src/libstd/map.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/map.rs b/src/libstd/map.rs index ed37318246b1..09eb1534f937 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -95,6 +95,7 @@ iface map { Iterate over all the keys in the map */ fn keys(fn(K)); + /* Iterate over all the values in the map */ @@ -631,4 +632,4 @@ mod tests { map.insert(key, "val"); assert (option::get(map.find(key)) == "val"); } -} \ No newline at end of file +} From 29ba19633651e4c51cddf3c2c089c1c36ed531c6 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Sat, 28 Jan 2012 15:41:53 -0800 Subject: [PATCH 6/6] Adding a function to concatanate vectors with a separator --- src/libcore/vec.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 3e888008c684..dd256af1d6f5 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -599,6 +599,21 @@ fn concat(v: [const [const T]]) -> [T] { ret new; } +/* +Function: connect + +Concatenate a vector of vectors, placing a given separator between each +*/ +fn connect(v: [const [const T]], sep: T) -> [T] { + let new: [T] = []; + let first = true; + for inner: [T] in v { + if first { first = false; } else { push(new, sep); } + new += inner; + } + ret new; +} + /* Function: foldl @@ -1927,6 +1942,13 @@ mod tests { assert concat([[1], [2,3]]) == [1, 2, 3]; } + #[test] + fn test_connect() { + assert connect([], 0) == []; + assert connect([[1], [2, 3]], 0) == [1, 0, 2, 3]; + assert connect([[1], [2], [3]], 0) == [1, 0, 2, 0, 3]; + } + #[test] fn test_windowed () { assert [[1u,2u,3u],[2u,3u,4u],[3u,4u,5u],[4u,5u,6u]]