โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
// Replicate Elements N Times โ 99 Problems #15
// replicate [a, b, c] 3 โ [a, a, a, b, b, b, c, c, c]
fn replicate<T: Clone>(lst: &[T], n: usize) -> Vec<T> {
lst.iter().flat_map(|x| vec![x.clone(); n]).collect()
}
/// Tail-recursive style.
fn replicate_tr<T: Clone>(lst: &[T], n: usize) -> Vec<T> {
let mut acc = Vec::with_capacity(lst.len() * n);
for x in lst {
for _ in 0..n {
acc.push(x.clone());
}
}
acc
}
/// Using concat_map + repeat โ explicit iterator approach.
fn replicate_map<T: Clone>(lst: &[T], n: usize) -> Vec<T> {
lst.iter()
.flat_map(|x| std::iter::repeat(x.clone()).take(n))
.collect()
}
fn main() {
let input = vec!['a', 'b', 'c'];
println!("Input: {:?}", input);
println!("x3: {:?}", replicate(&input, 3));
println!("x1: {:?}", replicate(&input, 1));
println!("x0: {:?}", replicate(&input, 0));
println!("TR x2: {:?}", replicate_tr(&[1, 2], 2));
println!("Map x3: {:?}", replicate_map(&input, 3));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_replicate_zero() {
assert_eq!(replicate(&[1, 2, 3], 0), vec![]);
}
#[test]
fn test_replicate_one() {
assert_eq!(replicate(&[1, 2, 3], 1), vec![1, 2, 3]);
}
#[test]
fn test_replicate_three() {
assert_eq!(
replicate(&['a', 'b', 'c'], 3),
vec!['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']
);
}
#[test]
fn test_all_versions_match() {
let input = vec![1, 2];
assert_eq!(replicate(&input, 3), replicate_tr(&input, 3));
assert_eq!(replicate(&input, 3), replicate_map(&input, 3));
}
}
(* Replicate Elements N Times โ 99 Problems #15 *)
(* replicate [a;b;c] 3 โ [a;a;a;b;b;b;c;c;c] *)
(* โโ Recursive with helper โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let replicate lst n =
let rec repeat x = function
| 0 -> []
| k -> x :: repeat x (k - 1)
in
let rec aux = function
| [] -> []
| h :: t -> repeat h n @ aux t
in aux lst
(* โโ Tail-recursive โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let replicate_tr lst n =
let rec aux acc = function
| [] -> List.rev acc
| h :: t ->
let rec add_n acc = function
| 0 -> aux acc t
| k -> add_n (h :: acc) (k - 1)
in add_n acc n
in aux [] lst
(* โโ Using concat_map + List.init โโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let replicate_map lst n =
List.concat_map (fun x -> List.init n (fun _ -> x)) lst
(* โโ Tests โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ *)
let () =
assert (replicate [] 5 = []);
assert (replicate [1;2;3] 0 = []);
assert (replicate [1;2;3] 1 = [1;2;3]);
assert (replicate ['a';'b';'c'] 3 = ['a';'a';'a';'b';'b';'b';'c';'c';'c']);
assert (replicate_tr [1;2] 3 = [1;1;1;2;2;2]);
assert (replicate_map [1;2] 2 = [1;1;2;2]);
print_endline "โ Replicate tests passed"
let replicate lst n =
let rec repeat x = function
| 0 -> []
| k -> x :: repeat x (k - 1)
in List.concat_map (fun x -> repeat x n) lstlet replicate lst n = List.concat_map (fun x -> List.init n (fun _ -> x)) lstpub fn replicate<T: Clone>(list: &[T], n: usize) -> Vec<T> {
list.iter()
.flat_map(|x| std::iter::repeat(x.clone()).take(n))
.collect()
}
The pre-allocated imperative version is optimal for performance:
let mut result = Vec::with_capacity(list.len() * n);
for item in list { for _ in 0..n { result.push(item.clone()); } }| Aspect | OCaml | Rust |
|---|---|---|
| Repeat combinator | `List.init n (fun _ -> x)` | `repeat(x).take(n)` |
| Expansion | `concat_map` | `flat_map` |
| Memory | Intermediate lists (GC) | Lazy iterator (zero-cost) |
| Pre-allocation | Not possible (linked list) | `Vec::with_capacity(len * n)` |
| n = 0 | Returns `[]` naturally | Returns empty Vec |